From cc134cad32eb1c657290b957cc37f1a79f5086bf Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 6 Jan 2024 23:59:34 +0900 Subject: [PATCH 001/255] =?UTF-8?q?Feat:=20=EA=B8=B0=EC=B4=88=20=EC=84=B8?= =?UTF-8?q?=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 완전 기초 세팅입니다. (더 보완해서 올릴 예정입니다) --- .gitignore | 37 +++ build.gradle | 35 +++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 249 ++++++++++++++++++ gradlew.bat | 92 +++++++ settings.gradle | 1 + src/main/java/friend/spring/Application.java | 13 + src/main/resources/application.properties | 1 + .../java/friend/spring/ApplicationTests.java | 13 + 10 files changed, 448 insertions(+) create mode 100644 .gitignore create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle create mode 100644 src/main/java/friend/spring/Application.java create mode 100644 src/main/resources/application.properties create mode 100644 src/test/java/friend/spring/ApplicationTests.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c2065bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..8a268e6 --- /dev/null +++ b/build.gradle @@ -0,0 +1,35 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.2.1' + id 'io.spring.dependency-management' version '1.1.4' +} + +group = 'friend' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '17' +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { +// implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' +// runtimeOnly 'com.mysql:mysql-connector-j' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..d64cd4917707c1f8861d8cb53dd15194d4248596 GIT binary patch literal 43462 zcma&NWl&^owk(X(xVyW%ySuwf;qI=D6|RlDJ2cR^yEKh!@I- zp9QeisK*rlxC>+~7Dk4IxIRsKBHqdR9b3+fyL=ynHmIDe&|>O*VlvO+%z5;9Z$|DJ zb4dO}-R=MKr^6EKJiOrJdLnCJn>np?~vU-1sSFgPu;pthGwf}bG z(1db%xwr#x)r+`4AGu$j7~u2MpVs3VpLp|mx&;>`0p0vH6kF+D2CY0fVdQOZ@h;A` z{infNyvmFUiu*XG}RNMNwXrbec_*a3N=2zJ|Wh5z* z5rAX$JJR{#zP>KY**>xHTuw?|-Rg|o24V)74HcfVT;WtQHXlE+_4iPE8QE#DUm%x0 zEKr75ur~W%w#-My3Tj`hH6EuEW+8K-^5P62$7Sc5OK+22qj&Pd1;)1#4tKihi=~8C zHiQSst0cpri6%OeaR`PY>HH_;CPaRNty%WTm4{wDK8V6gCZlG@U3$~JQZ;HPvDJcT1V{ z?>H@13MJcCNe#5z+MecYNi@VT5|&UiN1D4ATT+%M+h4c$t;C#UAs3O_q=GxK0}8%8 z8J(_M9bayxN}69ex4dzM_P3oh@ZGREjVvn%%r7=xjkqxJP4kj}5tlf;QosR=%4L5y zWhgejO=vao5oX%mOHbhJ8V+SG&K5dABn6!WiKl{|oPkq(9z8l&Mm%(=qGcFzI=eLu zWc_oCLyf;hVlB@dnwY98?75B20=n$>u3b|NB28H0u-6Rpl((%KWEBOfElVWJx+5yg z#SGqwza7f}$z;n~g%4HDU{;V{gXIhft*q2=4zSezGK~nBgu9-Q*rZ#2f=Q}i2|qOp z!!y4p)4o=LVUNhlkp#JL{tfkhXNbB=Ox>M=n6soptJw-IDI|_$is2w}(XY>a=H52d z3zE$tjPUhWWS+5h=KVH&uqQS=$v3nRs&p$%11b%5qtF}S2#Pc`IiyBIF4%A!;AVoI zXU8-Rpv!DQNcF~(qQnyyMy=-AN~U>#&X1j5BLDP{?K!%h!;hfJI>$mdLSvktEr*89 zdJHvby^$xEX0^l9g$xW-d?J;L0#(`UT~zpL&*cEh$L|HPAu=P8`OQZV!-}l`noSp_ zQ-1$q$R-gDL)?6YaM!=8H=QGW$NT2SeZlb8PKJdc=F-cT@j7Xags+Pr*jPtlHFnf- zh?q<6;)27IdPc^Wdy-mX%2s84C1xZq9Xms+==F4);O`VUASmu3(RlgE#0+#giLh-& zcxm3_e}n4{%|X zJp{G_j+%`j_q5}k{eW&TlP}J2wtZ2^<^E(O)4OQX8FDp6RJq!F{(6eHWSD3=f~(h} zJXCf7=r<16X{pHkm%yzYI_=VDP&9bmI1*)YXZeB}F? z(%QsB5fo*FUZxK$oX~X^69;x~j7ms8xlzpt-T15e9}$4T-pC z6PFg@;B-j|Ywajpe4~bk#S6(fO^|mm1hKOPfA%8-_iGCfICE|=P_~e;Wz6my&)h_~ zkv&_xSAw7AZ%ThYF(4jADW4vg=oEdJGVOs>FqamoL3Np8>?!W#!R-0%2Bg4h?kz5I zKV-rKN2n(vUL%D<4oj@|`eJ>0i#TmYBtYmfla;c!ATW%;xGQ0*TW@PTlGG><@dxUI zg>+3SiGdZ%?5N=8uoLA|$4isK$aJ%i{hECP$bK{J#0W2gQ3YEa zZQ50Stn6hqdfxJ*9#NuSLwKFCUGk@c=(igyVL;;2^wi4o30YXSIb2g_ud$ zgpCr@H0qWtk2hK8Q|&wx)}4+hTYlf;$a4#oUM=V@Cw#!$(nOFFpZ;0lc!qd=c$S}Z zGGI-0jg~S~cgVT=4Vo)b)|4phjStD49*EqC)IPwyeKBLcN;Wu@Aeph;emROAwJ-0< z_#>wVm$)ygH|qyxZaet&(Vf%pVdnvKWJn9`%DAxj3ot;v>S$I}jJ$FLBF*~iZ!ZXE zkvui&p}fI0Y=IDX)mm0@tAd|fEHl~J&K}ZX(Mm3cm1UAuwJ42+AO5@HwYfDH7ipIc zmI;1J;J@+aCNG1M`Btf>YT>~c&3j~Qi@Py5JT6;zjx$cvOQW@3oQ>|}GH?TW-E z1R;q^QFjm5W~7f}c3Ww|awg1BAJ^slEV~Pk`Kd`PS$7;SqJZNj->it4DW2l15}xP6 zoCl$kyEF%yJni0(L!Z&14m!1urXh6Btj_5JYt1{#+H8w?5QI%% zo-$KYWNMJVH?Hh@1n7OSu~QhSswL8x0=$<8QG_zepi_`y_79=nK=_ZP_`Em2UI*tyQoB+r{1QYZCpb?2OrgUw#oRH$?^Tj!Req>XiE#~B|~ z+%HB;=ic+R@px4Ld8mwpY;W^A%8%l8$@B@1m5n`TlKI6bz2mp*^^^1mK$COW$HOfp zUGTz-cN9?BGEp}5A!mDFjaiWa2_J2Iq8qj0mXzk; z66JBKRP{p%wN7XobR0YjhAuW9T1Gw3FDvR5dWJ8ElNYF94eF3ebu+QwKjtvVu4L zI9ip#mQ@4uqVdkl-TUQMb^XBJVLW(-$s;Nq;@5gr4`UfLgF$adIhd?rHOa%D);whv z=;krPp~@I+-Z|r#s3yCH+c1US?dnm+C*)r{m+86sTJusLdNu^sqLrfWed^ndHXH`m zd3#cOe3>w-ga(Dus_^ppG9AC>Iq{y%%CK+Cro_sqLCs{VLuK=dev>OL1dis4(PQ5R zcz)>DjEkfV+MO;~>VUlYF00SgfUo~@(&9$Iy2|G0T9BSP?&T22>K46D zL*~j#yJ?)^*%J3!16f)@Y2Z^kS*BzwfAQ7K96rFRIh>#$*$_Io;z>ux@}G98!fWR@ zGTFxv4r~v)Gsd|pF91*-eaZ3Qw1MH$K^7JhWIdX%o$2kCbvGDXy)a?@8T&1dY4`;L z4Kn+f%SSFWE_rpEpL9bnlmYq`D!6F%di<&Hh=+!VI~j)2mfil03T#jJ_s?}VV0_hp z7T9bWxc>Jm2Z0WMU?`Z$xE74Gu~%s{mW!d4uvKCx@WD+gPUQ zV0vQS(Ig++z=EHN)BR44*EDSWIyT~R4$FcF*VEY*8@l=218Q05D2$|fXKFhRgBIEE zdDFB}1dKkoO^7}{5crKX!p?dZWNz$m>1icsXG2N+((x0OIST9Zo^DW_tytvlwXGpn zs8?pJXjEG;T@qrZi%#h93?FP$!&P4JA(&H61tqQi=opRzNpm zkrG}$^t9&XduK*Qa1?355wd8G2CI6QEh@Ua>AsD;7oRUNLPb76m4HG3K?)wF~IyS3`fXuNM>${?wmB zpVz;?6_(Fiadfd{vUCBM*_kt$+F3J+IojI;9L(gc9n3{sEZyzR9o!_mOwFC#tQ{Q~ zP3-`#uK#tP3Q7~Q;4H|wjZHO8h7e4IuBxl&vz2w~D8)w=Wtg31zpZhz%+kzSzL*dV zwp@{WU4i;hJ7c2f1O;7Mz6qRKeASoIv0_bV=i@NMG*l<#+;INk-^`5w@}Dj~;k=|}qM1vq_P z|GpBGe_IKq|LNy9SJhKOQ$c=5L{Dv|Q_lZl=-ky*BFBJLW9&y_C|!vyM~rQx=!vun z?rZJQB5t}Dctmui5i31C_;_}CEn}_W%>oSXtt>@kE1=JW*4*v4tPp;O6 zmAk{)m!)}34pTWg8{i>($%NQ(Tl;QC@J@FfBoc%Gr&m560^kgSfodAFrIjF}aIw)X zoXZ`@IsMkc8_=w%-7`D6Y4e*CG8k%Ud=GXhsTR50jUnm+R*0A(O3UKFg0`K;qp1bl z7``HN=?39ic_kR|^R^~w-*pa?Vj#7|e9F1iRx{GN2?wK!xR1GW!qa=~pjJb-#u1K8 zeR?Y2i-pt}yJq;SCiVHODIvQJX|ZJaT8nO+(?HXbLefulKKgM^B(UIO1r+S=7;kLJ zcH}1J=Px2jsh3Tec&v8Jcbng8;V-`#*UHt?hB(pmOipKwf3Lz8rG$heEB30Sg*2rx zV<|KN86$soN(I!BwO`1n^^uF2*x&vJ$2d$>+`(romzHP|)K_KkO6Hc>_dwMW-M(#S zK(~SiXT1@fvc#U+?|?PniDRm01)f^#55;nhM|wi?oG>yBsa?~?^xTU|fX-R(sTA+5 zaq}-8Tx7zrOy#3*JLIIVsBmHYLdD}!0NP!+ITW+Thn0)8SS!$@)HXwB3tY!fMxc#1 zMp3H?q3eD?u&Njx4;KQ5G>32+GRp1Ee5qMO0lZjaRRu&{W<&~DoJNGkcYF<5(Ab+J zgO>VhBl{okDPn78<%&e2mR{jwVCz5Og;*Z;;3%VvoGo_;HaGLWYF7q#jDX=Z#Ml`H z858YVV$%J|e<1n`%6Vsvq7GmnAV0wW4$5qQ3uR@1i>tW{xrl|ExywIc?fNgYlA?C5 zh$ezAFb5{rQu6i7BSS5*J-|9DQ{6^BVQ{b*lq`xS@RyrsJN?-t=MTMPY;WYeKBCNg z^2|pN!Q^WPJuuO4!|P@jzt&tY1Y8d%FNK5xK(!@`jO2aEA*4 zkO6b|UVBipci?){-Ke=+1;mGlND8)6+P;8sq}UXw2hn;fc7nM>g}GSMWu&v&fqh

iViYT=fZ(|3Ox^$aWPp4a8h24tD<|8-!aK0lHgL$N7Efw}J zVIB!7=T$U`ao1?upi5V4Et*-lTG0XvExbf!ya{cua==$WJyVG(CmA6Of*8E@DSE%L z`V^$qz&RU$7G5mg;8;=#`@rRG`-uS18$0WPN@!v2d{H2sOqP|!(cQ@ zUHo!d>>yFArLPf1q`uBvY32miqShLT1B@gDL4XoVTK&@owOoD)OIHXrYK-a1d$B{v zF^}8D3Y^g%^cnvScOSJR5QNH+BI%d|;J;wWM3~l>${fb8DNPg)wrf|GBP8p%LNGN# z3EaIiItgwtGgT&iYCFy9-LG}bMI|4LdmmJt@V@% zb6B)1kc=T)(|L@0;wr<>=?r04N;E&ef+7C^`wPWtyQe(*pD1pI_&XHy|0gIGHMekd zF_*M4yi6J&Z4LQj65)S zXwdM{SwUo%3SbPwFsHgqF@V|6afT|R6?&S;lw=8% z3}@9B=#JI3@B*#4s!O))~z zc>2_4Q_#&+5V`GFd?88^;c1i7;Vv_I*qt!_Yx*n=;rj!82rrR2rQ8u5(Ejlo{15P% zs~!{%XJ>FmJ})H^I9bn^Re&38H{xA!0l3^89k(oU;bZWXM@kn$#aoS&Y4l^-WEn-fH39Jb9lA%s*WsKJQl?n9B7_~P z-XM&WL7Z!PcoF6_D>V@$CvUIEy=+Z&0kt{szMk=f1|M+r*a43^$$B^MidrT0J;RI` z(?f!O<8UZkm$_Ny$Hth1J#^4ni+im8M9mr&k|3cIgwvjAgjH z8`N&h25xV#v*d$qBX5jkI|xOhQn!>IYZK7l5#^P4M&twe9&Ey@@GxYMxBZq2e7?`q z$~Szs0!g{2fGcp9PZEt|rdQ6bhAgpcLHPz?f-vB?$dc*!9OL?Q8mn7->bFD2Si60* z!O%y)fCdMSV|lkF9w%x~J*A&srMyYY3{=&$}H zGQ4VG_?$2X(0|vT0{=;W$~icCI{b6W{B!Q8xdGhF|D{25G_5_+%s(46lhvNLkik~R z>nr(&C#5wwOzJZQo9m|U<;&Wk!_#q|V>fsmj1g<6%hB{jGoNUPjgJslld>xmODzGjYc?7JSuA?A_QzjDw5AsRgi@Y|Z0{F{!1=!NES-#*f^s4l0Hu zz468))2IY5dmD9pa*(yT5{EyP^G>@ZWumealS-*WeRcZ}B%gxq{MiJ|RyX-^C1V=0 z@iKdrGi1jTe8Ya^x7yyH$kBNvM4R~`fbPq$BzHum-3Zo8C6=KW@||>zsA8-Y9uV5V z#oq-f5L5}V<&wF4@X@<3^C%ptp6+Ce)~hGl`kwj)bsAjmo_GU^r940Z-|`<)oGnh7 zFF0Tde3>ui?8Yj{sF-Z@)yQd~CGZ*w-6p2U<8}JO-sRsVI5dBji`01W8A&3$?}lxBaC&vn0E$c5tW* zX>5(zzZ=qn&!J~KdsPl;P@bmA-Pr8T*)eh_+Dv5=Ma|XSle6t(k8qcgNyar{*ReQ8 zTXwi=8vr>!3Ywr+BhggHDw8ke==NTQVMCK`$69fhzEFB*4+H9LIvdt-#IbhZvpS}} zO3lz;P?zr0*0$%-Rq_y^k(?I{Mk}h@w}cZpMUp|ucs55bcloL2)($u%mXQw({Wzc~ z;6nu5MkjP)0C(@%6Q_I_vsWrfhl7Zpoxw#WoE~r&GOSCz;_ro6i(^hM>I$8y>`!wW z*U^@?B!MMmb89I}2(hcE4zN2G^kwyWCZp5JG>$Ez7zP~D=J^LMjSM)27_0B_X^C(M z`fFT+%DcKlu?^)FCK>QzSnV%IsXVcUFhFdBP!6~se&xxrIxsvySAWu++IrH;FbcY$ z2DWTvSBRfLwdhr0nMx+URA$j3i7_*6BWv#DXfym?ZRDcX9C?cY9sD3q)uBDR3uWg= z(lUIzB)G$Hr!){>E{s4Dew+tb9kvToZp-1&c?y2wn@Z~(VBhqz`cB;{E4(P3N2*nJ z_>~g@;UF2iG{Kt(<1PyePTKahF8<)pozZ*xH~U-kfoAayCwJViIrnqwqO}7{0pHw$ zs2Kx?s#vQr7XZ264>5RNKSL8|Ty^=PsIx^}QqOOcfpGUU4tRkUc|kc7-!Ae6!+B{o~7nFpm3|G5^=0#Bnm6`V}oSQlrX(u%OWnC zoLPy&Q;1Jui&7ST0~#+}I^&?vcE*t47~Xq#YwvA^6^} z`WkC)$AkNub|t@S!$8CBlwbV~?yp&@9h{D|3z-vJXgzRC5^nYm+PyPcgRzAnEi6Q^gslXYRv4nycsy-SJu?lMps-? zV`U*#WnFsdPLL)Q$AmD|0`UaC4ND07+&UmOu!eHruzV|OUox<+Jl|Mr@6~C`T@P%s zW7sgXLF2SSe9Fl^O(I*{9wsFSYb2l%-;&Pi^dpv!{)C3d0AlNY6!4fgmSgj_wQ*7Am7&$z;Jg&wgR-Ih;lUvWS|KTSg!&s_E9_bXBkZvGiC6bFKDWZxsD$*NZ#_8bl zG1P-#@?OQzED7@jlMJTH@V!6k;W>auvft)}g zhoV{7$q=*;=l{O>Q4a@ ziMjf_u*o^PsO)#BjC%0^h>Xp@;5$p{JSYDt)zbb}s{Kbt!T*I@Pk@X0zds6wsefuU zW$XY%yyRGC94=6mf?x+bbA5CDQ2AgW1T-jVAJbm7K(gp+;v6E0WI#kuACgV$r}6L? zd|Tj?^%^*N&b>Dd{Wr$FS2qI#Ucs1yd4N+RBUQiSZGujH`#I)mG&VKoDh=KKFl4=G z&MagXl6*<)$6P}*Tiebpz5L=oMaPrN+caUXRJ`D?=K9!e0f{@D&cZLKN?iNP@X0aF zE(^pl+;*T5qt?1jRC=5PMgV!XNITRLS_=9{CJExaQj;lt!&pdzpK?8p>%Mb+D z?yO*uSung=-`QQ@yX@Hyd4@CI^r{2oiu`%^bNkz+Nkk!IunjwNC|WcqvX~k=><-I3 zDQdbdb|!v+Iz01$w@aMl!R)koD77Xp;eZwzSl-AT zr@Vu{=xvgfq9akRrrM)}=!=xcs+U1JO}{t(avgz`6RqiiX<|hGG1pmop8k6Q+G_mv zJv|RfDheUp2L3=^C=4aCBMBn0aRCU(DQwX-W(RkRwmLeuJYF<0urcaf(=7)JPg<3P zQs!~G)9CT18o!J4{zX{_e}4eS)U-E)0FAt}wEI(c0%HkxgggW;(1E=>J17_hsH^sP z%lT0LGgbUXHx-K*CI-MCrP66UP0PvGqM$MkeLyqHdbgP|_Cm!7te~b8p+e6sQ_3k| zVcwTh6d83ltdnR>D^)BYQpDKlLk3g0Hdcgz2}%qUs9~~Rie)A-BV1mS&naYai#xcZ z(d{8=-LVpTp}2*y)|gR~;qc7fp26}lPcLZ#=JpYcn3AT9(UIdOyg+d(P5T7D&*P}# zQCYplZO5|7+r19%9e`v^vfSS1sbX1c%=w1;oyruXB%Kl$ACgKQ6=qNWLsc=28xJjg zwvsI5-%SGU|3p>&zXVl^vVtQT3o-#$UT9LI@Npz~6=4!>mc431VRNN8od&Ul^+G_kHC`G=6WVWM z%9eWNyy(FTO|A+@x}Ou3CH)oi;t#7rAxdIXfNFwOj_@Y&TGz6P_sqiB`Q6Lxy|Q{`|fgmRG(k+!#b*M+Z9zFce)f-7;?Km5O=LHV9f9_87; zF7%R2B+$?@sH&&-$@tzaPYkw0;=i|;vWdI|Wl3q_Zu>l;XdIw2FjV=;Mq5t1Q0|f< zs08j54Bp`3RzqE=2enlkZxmX6OF+@|2<)A^RNQpBd6o@OXl+i)zO%D4iGiQNuXd+zIR{_lb96{lc~bxsBveIw6umhShTX+3@ZJ=YHh@ zWY3(d0azg;7oHn>H<>?4@*RQbi>SmM=JrHvIG(~BrvI)#W(EAeO6fS+}mxxcc+X~W6&YVl86W9WFSS}Vz-f9vS?XUDBk)3TcF z8V?$4Q)`uKFq>xT=)Y9mMFVTUk*NIA!0$?RP6Ig0TBmUFrq*Q-Agq~DzxjStQyJ({ zBeZ;o5qUUKg=4Hypm|}>>L=XKsZ!F$yNTDO)jt4H0gdQ5$f|d&bnVCMMXhNh)~mN z@_UV6D7MVlsWz+zM+inZZp&P4fj=tm6fX)SG5H>OsQf_I8c~uGCig$GzuwViK54bcgL;VN|FnyQl>Ed7(@>=8$a_UKIz|V6CeVSd2(P z0Uu>A8A+muM%HLFJQ9UZ5c)BSAv_zH#1f02x?h9C}@pN@6{>UiAp>({Fn(T9Q8B z^`zB;kJ5b`>%dLm+Ol}ty!3;8f1XDSVX0AUe5P#@I+FQ-`$(a;zNgz)4x5hz$Hfbg z!Q(z26wHLXko(1`;(BAOg_wShpX0ixfWq3ponndY+u%1gyX)_h=v1zR#V}#q{au6; z!3K=7fQwnRfg6FXtNQmP>`<;!N137paFS%y?;lb1@BEdbvQHYC{976l`cLqn;b8lp zIDY>~m{gDj(wfnK!lpW6pli)HyLEiUrNc%eXTil|F2s(AY+LW5hkKb>TQ3|Q4S9rr zpDs4uK_co6XPsn_z$LeS{K4jFF`2>U`tbgKdyDne`xmR<@6AA+_hPNKCOR-Zqv;xk zu5!HsBUb^!4uJ7v0RuH-7?l?}b=w5lzzXJ~gZcxRKOovSk@|#V+MuX%Y+=;14i*%{)_gSW9(#4%)AV#3__kac1|qUy!uyP{>?U#5wYNq}y$S9pCc zFc~4mgSC*G~j0u#qqp9 z${>3HV~@->GqEhr_Xwoxq?Hjn#=s2;i~g^&Hn|aDKpA>Oc%HlW(KA1?BXqpxB;Ydx)w;2z^MpjJ(Qi(X!$5RC z*P{~%JGDQqojV>2JbEeCE*OEu!$XJ>bWA9Oa_Hd;y)F%MhBRi*LPcdqR8X`NQ&1L# z5#9L*@qxrx8n}LfeB^J{%-?SU{FCwiWyHp682F+|pa+CQa3ZLzBqN1{)h4d6+vBbV zC#NEbQLC;}me3eeYnOG*nXOJZEU$xLZ1<1Y=7r0(-U0P6-AqwMAM`a(Ed#7vJkn6plb4eI4?2y3yOTGmmDQ!z9`wzbf z_OY#0@5=bnep;MV0X_;;SJJWEf^E6Bd^tVJ9znWx&Ks8t*B>AM@?;D4oWUGc z!H*`6d7Cxo6VuyS4Eye&L1ZRhrRmN6Lr`{NL(wDbif|y&z)JN>Fl5#Wi&mMIr5i;x zBx}3YfF>>8EC(fYnmpu~)CYHuHCyr5*`ECap%t@y=jD>!_%3iiE|LN$mK9>- zHdtpy8fGZtkZF?%TW~29JIAfi2jZT8>OA7=h;8T{{k?c2`nCEx9$r zS+*&vt~2o^^J+}RDG@+9&M^K*z4p{5#IEVbz`1%`m5c2};aGt=V?~vIM}ZdPECDI)47|CWBCfDWUbxBCnmYivQ*0Nu_xb*C>~C9(VjHM zxe<*D<#dQ8TlpMX2c@M<9$w!RP$hpG4cs%AI){jp*Sj|*`m)5(Bw*A0$*i-(CA5#%>a)$+jI2C9r6|(>J8InryENI z$NohnxDUB;wAYDwrb*!N3noBTKPpPN}~09SEL18tkG zxgz(RYU_;DPT{l?Q$+eaZaxnsWCA^ds^0PVRkIM%bOd|G2IEBBiz{&^JtNsODs;5z zICt_Zj8wo^KT$7Bg4H+y!Df#3mbl%%?|EXe!&(Vmac1DJ*y~3+kRKAD=Ovde4^^%~ zw<9av18HLyrf*_>Slp;^i`Uy~`mvBjZ|?Ad63yQa#YK`4+c6;pW4?XIY9G1(Xh9WO8{F-Aju+nS9Vmv=$Ac0ienZ+p9*O%NG zMZKy5?%Z6TAJTE?o5vEr0r>f>hb#2w2U3DL64*au_@P!J!TL`oH2r*{>ffu6|A7tv zL4juf$DZ1MW5ZPsG!5)`k8d8c$J$o;%EIL0va9&GzWvkS%ZsGb#S(?{!UFOZ9<$a| zY|a+5kmD5N&{vRqkgY>aHsBT&`rg|&kezoD)gP0fsNYHsO#TRc_$n6Lf1Z{?+DLziXlHrq4sf(!>O{?Tj;Eh@%)+nRE_2VxbN&&%%caU#JDU%vL3}Cb zsb4AazPI{>8H&d=jUaZDS$-0^AxE@utGs;-Ez_F(qC9T=UZX=>ok2k2 ziTn{K?y~a5reD2A)P${NoI^>JXn>`IeArow(41c-Wm~)wiryEP(OS{YXWi7;%dG9v zI?mwu1MxD{yp_rrk!j^cKM)dc4@p4Ezyo%lRN|XyD}}>v=Xoib0gOcdXrQ^*61HNj z=NP|pd>@yfvr-=m{8$3A8TQGMTE7g=z!%yt`8`Bk-0MMwW~h^++;qyUP!J~ykh1GO z(FZ59xuFR$(WE;F@UUyE@Sp>`aVNjyj=Ty>_Vo}xf`e7`F;j-IgL5`1~-#70$9_=uBMq!2&1l zomRgpD58@)YYfvLtPW}{C5B35R;ZVvB<<#)x%srmc_S=A7F@DW8>QOEGwD6suhwCg z>Pa+YyULhmw%BA*4yjDp|2{!T98~<6Yfd(wo1mQ!KWwq0eg+6)o1>W~f~kL<-S+P@$wx*zeI|1t7z#Sxr5 zt6w+;YblPQNplq4Z#T$GLX#j6yldXAqj>4gAnnWtBICUnA&-dtnlh=t0Ho_vEKwV` z)DlJi#!@nkYV#$!)@>udAU*hF?V`2$Hf=V&6PP_|r#Iv*J$9)pF@X3`k;5})9^o4y z&)~?EjX5yX12O(BsFy-l6}nYeuKkiq`u9145&3Ssg^y{5G3Pse z9w(YVa0)N-fLaBq1`P!_#>SS(8fh_5!f{UrgZ~uEdeMJIz7DzI5!NHHqQtm~#CPij z?=N|J>nPR6_sL7!f4hD_|KH`vf8(Wpnj-(gPWH+ZvID}%?~68SwhPTC3u1_cB`otq z)U?6qo!ZLi5b>*KnYHWW=3F!p%h1;h{L&(Q&{qY6)_qxNfbP6E3yYpW!EO+IW3?@J z);4>g4gnl^8klu7uA>eGF6rIGSynacogr)KUwE_R4E5Xzi*Qir@b-jy55-JPC8c~( zo!W8y9OGZ&`xmc8;=4-U9=h{vCqfCNzYirONmGbRQlR`WWlgnY+1wCXbMz&NT~9*| z6@FrzP!LX&{no2!Ln_3|I==_4`@}V?4a;YZKTdw;vT<+K+z=uWbW(&bXEaWJ^W8Td z-3&1bY^Z*oM<=M}LVt>_j+p=2Iu7pZmbXrhQ_k)ysE9yXKygFNw$5hwDn(M>H+e1&9BM5!|81vd%r%vEm zqxY3?F@fb6O#5UunwgAHR9jp_W2zZ}NGp2%mTW@(hz7$^+a`A?mb8|_G*GNMJ) zjqegXQio=i@AINre&%ofexAr95aop5C+0MZ0m-l=MeO8m3epm7U%vZB8+I+C*iNFM z#T3l`gknX;D$-`2XT^Cg*vrv=RH+P;_dfF++cP?B_msQI4j+lt&rX2)3GaJx%W*Nn zkML%D{z5tpHH=dksQ*gzc|}gzW;lwAbxoR07VNgS*-c3d&8J|;@3t^ zVUz*J*&r7DFRuFVDCJDK8V9NN5hvpgGjwx+5n)qa;YCKe8TKtdnh{I7NU9BCN!0dq zczrBk8pE{{@vJa9ywR@mq*J=v+PG;?fwqlJVhijG!3VmIKs>9T6r7MJpC)m!Tc#>g zMtVsU>wbwFJEfwZ{vB|ZlttNe83)$iz`~#8UJ^r)lJ@HA&G#}W&ZH*;k{=TavpjWE z7hdyLZPf*X%Gm}i`Y{OGeeu^~nB8=`{r#TUrM-`;1cBvEd#d!kPqIgYySYhN-*1;L z^byj%Yi}Gx)Wnkosi337BKs}+5H5dth1JA{Ir-JKN$7zC)*}hqeoD(WfaUDPT>0`- z(6sa0AoIqASwF`>hP}^|)a_j2s^PQn*qVC{Q}htR z5-)duBFXT_V56-+UohKXlq~^6uf!6sA#ttk1o~*QEy_Y-S$gAvq47J9Vtk$5oA$Ct zYhYJ@8{hsC^98${!#Ho?4y5MCa7iGnfz}b9jE~h%EAAv~Qxu)_rAV;^cygV~5r_~?l=B`zObj7S=H=~$W zPtI_m%g$`kL_fVUk9J@>EiBH zOO&jtn~&`hIFMS5S`g8w94R4H40mdNUH4W@@XQk1sr17b{@y|JB*G9z1|CrQjd+GX z6+KyURG3;!*BQrentw{B2R&@2&`2}n(z-2&X7#r!{yg@Soy}cRD~j zj9@UBW+N|4HW4AWapy4wfUI- zZ`gSL6DUlgj*f1hSOGXG0IVH8HxK?o2|3HZ;KW{K+yPAlxtb)NV_2AwJm|E)FRs&& z=c^e7bvUsztY|+f^k7NXs$o1EUq>cR7C0$UKi6IooHWlK_#?IWDkvywnzg&ThWo^? z2O_N{5X39#?eV9l)xI(>@!vSB{DLt*oY!K1R8}_?%+0^C{d9a%N4 zoxHVT1&Lm|uDX%$QrBun5e-F`HJ^T$ zmzv)p@4ZHd_w9!%Hf9UYNvGCw2TTTbrj9pl+T9%-_-}L(tES>Or-}Z4F*{##n3~L~TuxjirGuIY#H7{%$E${?p{Q01 zi6T`n;rbK1yIB9jmQNycD~yZq&mbIsFWHo|ZAChSFPQa<(%d8mGw*V3fh|yFoxOOiWJd(qvVb!Z$b88cg->N=qO*4k~6;R==|9ihg&riu#P~s4Oap9O7f%crSr^rljeIfXDEg>wi)&v*a%7zpz<9w z*r!3q9J|390x`Zk;g$&OeN&ctp)VKRpDSV@kU2Q>jtok($Y-*x8_$2piTxun81@vt z!Vj?COa0fg2RPXMSIo26T=~0d`{oGP*eV+$!0I<(4azk&Vj3SiG=Q!6mX0p$z7I}; z9BJUFgT-K9MQQ-0@Z=^7R<{bn2Fm48endsSs`V7_@%8?Bxkqv>BDoVcj?K#dV#uUP zL1ND~?D-|VGKe3Rw_7-Idpht>H6XRLh*U7epS6byiGvJpr%d}XwfusjH9g;Z98H`x zyde%%5mhGOiL4wljCaWCk-&uE4_OOccb9c!ZaWt4B(wYl!?vyzl%7n~QepN&eFUrw zFIOl9c({``6~QD+43*_tzP{f2x41h(?b43^y6=iwyB)2os5hBE!@YUS5?N_tXd=h( z)WE286Fbd>R4M^P{!G)f;h<3Q>Fipuy+d2q-)!RyTgt;wr$(?9ox3;q+{E*ZQHhOn;lM`cjnu9 zXa48ks-v(~b*;MAI<>YZH(^NV8vjb34beE<_cwKlJoR;k6lJNSP6v}uiyRD?|0w+X@o1ONrH8a$fCxXpf? z?$DL0)7|X}Oc%h^zrMKWc-NS9I0Utu@>*j}b@tJ=ixQSJ={4@854wzW@E>VSL+Y{i z#0b=WpbCZS>kUCO_iQz)LoE>P5LIG-hv9E+oG}DtlIDF>$tJ1aw9^LuhLEHt?BCj& z(O4I8v1s#HUi5A>nIS-JK{v!7dJx)^Yg%XjNmlkWAq2*cv#tHgz`Y(bETc6CuO1VkN^L-L3j_x<4NqYb5rzrLC-7uOv z!5e`GZt%B782C5-fGnn*GhDF$%(qP<74Z}3xx+{$4cYKy2ikxI7B2N+2r07DN;|-T->nU&!=Cm#rZt%O_5c&1Z%nlWq3TKAW0w zQqemZw_ue--2uKQsx+niCUou?HjD`xhEjjQd3%rrBi82crq*~#uA4+>vR<_S{~5ce z-2EIl?~s z1=GVL{NxP1N3%=AOaC}j_Fv=ur&THz zyO!d9kHq|c73kpq`$+t+8Bw7MgeR5~`d7ChYyGCBWSteTB>8WAU(NPYt2Dk`@#+}= zI4SvLlyk#pBgVigEe`?NG*vl7V6m+<}%FwPV=~PvvA)=#ths==DRTDEYh4V5}Cf$z@#;< zyWfLY_5sP$gc3LLl2x+Ii)#b2nhNXJ{R~vk`s5U7Nyu^3yFg&D%Txwj6QezMX`V(x z=C`{76*mNb!qHHs)#GgGZ_7|vkt9izl_&PBrsu@}L`X{95-2jf99K)0=*N)VxBX2q z((vkpP2RneSIiIUEnGb?VqbMb=Zia+rF~+iqslydE34cSLJ&BJW^3knX@M;t*b=EA zNvGzv41Ld_T+WT#XjDB840vovUU^FtN_)G}7v)1lPetgpEK9YS^OWFkPoE{ovj^=@ zO9N$S=G$1ecndT_=5ehth2Lmd1II-PuT~C9`XVePw$y8J#dpZ?Tss<6wtVglm(Ok7 z3?^oi@pPio6l&!z8JY(pJvG=*pI?GIOu}e^EB6QYk$#FJQ%^AIK$I4epJ+9t?KjqA+bkj&PQ*|vLttme+`9G=L% ziadyMw_7-M)hS(3E$QGNCu|o23|%O+VN7;Qggp?PB3K-iSeBa2b}V4_wY`G1Jsfz4 z9|SdB^;|I8E8gWqHKx!vj_@SMY^hLEIbSMCuE?WKq=c2mJK z8LoG-pnY!uhqFv&L?yEuxo{dpMTsmCn)95xanqBrNPTgXP((H$9N${Ow~Is-FBg%h z53;|Y5$MUN)9W2HBe2TD`ct^LHI<(xWrw}$qSoei?}s)&w$;&!14w6B6>Yr6Y8b)S z0r71`WmAvJJ`1h&poLftLUS6Ir zC$bG9!Im_4Zjse)#K=oJM9mHW1{%l8sz$1o?ltdKlLTxWWPB>Vk22czVt|1%^wnN@*!l)}?EgtvhC>vlHm^t+ogpgHI1_$1ox9e;>0!+b(tBrmXRB`PY1vp-R**8N7 zGP|QqI$m(Rdu#=(?!(N}G9QhQ%o!aXE=aN{&wtGP8|_qh+7a_j_sU5|J^)vxq;# zjvzLn%_QPHZZIWu1&mRAj;Sa_97p_lLq_{~j!M9N^1yp3U_SxRqK&JnR%6VI#^E12 z>CdOVI^_9aPK2eZ4h&^{pQs}xsijXgFYRIxJ~N7&BB9jUR1fm!(xl)mvy|3e6-B3j zJn#ajL;bFTYJ2+Q)tDjx=3IklO@Q+FFM}6UJr6km7hj7th9n_&JR7fnqC!hTZoM~T zBeaVFp%)0cbPhejX<8pf5HyRUj2>aXnXBqDJe73~J%P(2C?-RT{c3NjE`)om! zl$uewSgWkE66$Kb34+QZZvRn`fob~Cl9=cRk@Es}KQm=?E~CE%spXaMO6YmrMl%9Q zlA3Q$3|L1QJ4?->UjT&CBd!~ru{Ih^in&JXO=|<6J!&qp zRe*OZ*cj5bHYlz!!~iEKcuE|;U4vN1rk$xq6>bUWD*u(V@8sG^7>kVuo(QL@Ki;yL zWC!FT(q{E8#on>%1iAS0HMZDJg{Z{^!De(vSIq&;1$+b)oRMwA3nc3mdTSG#3uYO_ z>+x;7p4I;uHz?ZB>dA-BKl+t-3IB!jBRgdvAbW!aJ(Q{aT>+iz?91`C-xbe)IBoND z9_Xth{6?(y3rddwY$GD65IT#f3<(0o#`di{sh2gm{dw*#-Vnc3r=4==&PU^hCv$qd zjw;>i&?L*Wq#TxG$mFIUf>eK+170KG;~+o&1;Tom9}}mKo23KwdEM6UonXgc z!6N(@k8q@HPw{O8O!lAyi{rZv|DpgfU{py+j(X_cwpKqcalcqKIr0kM^%Br3SdeD> zHSKV94Yxw;pjzDHo!Q?8^0bb%L|wC;4U^9I#pd5O&eexX+Im{ z?jKnCcsE|H?{uGMqVie_C~w7GX)kYGWAg%-?8|N_1#W-|4F)3YTDC+QSq1s!DnOML3@d`mG%o2YbYd#jww|jD$gotpa)kntakp#K;+yo-_ZF9qrNZw<%#C zuPE@#3RocLgPyiBZ+R_-FJ_$xP!RzWm|aN)S+{$LY9vvN+IW~Kf3TsEIvP+B9Mtm! zpfNNxObWQpLoaO&cJh5>%slZnHl_Q~(-Tfh!DMz(dTWld@LG1VRF`9`DYKhyNv z2pU|UZ$#_yUx_B_|MxUq^glT}O5Xt(Vm4Mr02><%C)@v;vPb@pT$*yzJ4aPc_FZ3z z3}PLoMBIM>q_9U2rl^sGhk1VUJ89=*?7|v`{!Z{6bqFMq(mYiA?%KbsI~JwuqVA9$H5vDE+VocjX+G^%bieqx->s;XWlKcuv(s%y%D5Xbc9+ zc(_2nYS1&^yL*ey664&4`IoOeDIig}y-E~_GS?m;D!xv5-xwz+G`5l6V+}CpeJDi^ z%4ed$qowm88=iYG+(`ld5Uh&>Dgs4uPHSJ^TngXP_V6fPyl~>2bhi20QB%lSd#yYn zO05?KT1z@?^-bqO8Cg`;ft>ilejsw@2%RR7;`$Vs;FmO(Yr3Fp`pHGr@P2hC%QcA|X&N2Dn zYf`MqXdHi%cGR@%y7Rg7?d3?an){s$zA{!H;Ie5exE#c~@NhQUFG8V=SQh%UxUeiV zd7#UcYqD=lk-}sEwlpu&H^T_V0{#G?lZMxL7ih_&{(g)MWBnCZxtXg znr#}>U^6!jA%e}@Gj49LWG@*&t0V>Cxc3?oO7LSG%~)Y5}f7vqUUnQ;STjdDU}P9IF9d9<$;=QaXc zL1^X7>fa^jHBu_}9}J~#-oz3Oq^JmGR#?GO7b9a(=R@fw@}Q{{@`Wy1vIQ#Bw?>@X z-_RGG@wt|%u`XUc%W{J z>iSeiz8C3H7@St3mOr_mU+&bL#Uif;+Xw-aZdNYUpdf>Rvu0i0t6k*}vwU`XNO2he z%miH|1tQ8~ZK!zmL&wa3E;l?!!XzgV#%PMVU!0xrDsNNZUWKlbiOjzH-1Uoxm8E#r`#2Sz;-o&qcqB zC-O_R{QGuynW14@)7&@yw1U}uP(1cov)twxeLus0s|7ayrtT8c#`&2~Fiu2=R;1_4bCaD=*E@cYI>7YSnt)nQc zohw5CsK%m?8Ack)qNx`W0_v$5S}nO|(V|RZKBD+btO?JXe|~^Qqur%@eO~<8-L^9d z=GA3-V14ng9L29~XJ>a5k~xT2152zLhM*@zlp2P5Eu}bywkcqR;ISbas&#T#;HZSf z2m69qTV(V@EkY(1Dk3`}j)JMo%ZVJ*5eB zYOjIisi+igK0#yW*gBGj?@I{~mUOvRFQR^pJbEbzFxTubnrw(Muk%}jI+vXmJ;{Q6 zrSobKD>T%}jV4Ub?L1+MGOD~0Ir%-`iTnWZN^~YPrcP5y3VMAzQ+&en^VzKEb$K!Q z<7Dbg&DNXuow*eD5yMr+#08nF!;%4vGrJI++5HdCFcGLfMW!KS*Oi@=7hFwDG!h2< zPunUEAF+HncQkbfFj&pbzp|MU*~60Z(|Ik%Tn{BXMN!hZOosNIseT?R;A`W?=d?5X zK(FB=9mZusYahp|K-wyb={rOpdn=@;4YI2W0EcbMKyo~-#^?h`BA9~o285%oY zfifCh5Lk$SY@|2A@a!T2V+{^!psQkx4?x0HSV`(w9{l75QxMk!)U52Lbhn{8ol?S) zCKo*7R(z!uk<6*qO=wh!Pul{(qq6g6xW;X68GI_CXp`XwO zxuSgPRAtM8K7}5E#-GM!*ydOOG_{A{)hkCII<|2=ma*71ci_-}VPARm3crFQjLYV! z9zbz82$|l01mv`$WahE2$=fAGWkd^X2kY(J7iz}WGS z@%MyBEO=A?HB9=^?nX`@nh;7;laAjs+fbo!|K^mE!tOB>$2a_O0y-*uaIn8k^6Y zSbuv;5~##*4Y~+y7Z5O*3w4qgI5V^17u*ZeupVGH^nM&$qmAk|anf*>r zWc5CV;-JY-Z@Uq1Irpb^O`L_7AGiqd*YpGUShb==os$uN3yYvb`wm6d=?T*it&pDk zo`vhw)RZX|91^^Wa_ti2zBFyWy4cJu#g)_S6~jT}CC{DJ_kKpT`$oAL%b^!2M;JgT zM3ZNbUB?}kP(*YYvXDIH8^7LUxz5oE%kMhF!rnPqv!GiY0o}NR$OD=ITDo9r%4E>E0Y^R(rS^~XjWyVI6 zMOR5rPXhTp*G*M&X#NTL`Hu*R+u*QNoiOKg4CtNPrjgH>c?Hi4MUG#I917fx**+pJfOo!zFM&*da&G_x)L(`k&TPI*t3e^{crd zX<4I$5nBQ8Ax_lmNRa~E*zS-R0sxkz`|>7q_?*e%7bxqNm3_eRG#1ae3gtV9!fQpY z+!^a38o4ZGy9!J5sylDxZTx$JmG!wg7;>&5H1)>f4dXj;B+@6tMlL=)cLl={jLMxY zbbf1ax3S4>bwB9-$;SN2?+GULu;UA-35;VY*^9Blx)Jwyb$=U!D>HhB&=jSsd^6yw zL)?a|>GxU!W}ocTC(?-%z3!IUhw^uzc`Vz_g>-tv)(XA#JK^)ZnC|l1`@CdX1@|!| z_9gQ)7uOf?cR@KDp97*>6X|;t@Y`k_N@)aH7gY27)COv^P3ya9I{4z~vUjLR9~z1Z z5=G{mVtKH*&$*t0@}-i_v|3B$AHHYale7>E+jP`ClqG%L{u;*ff_h@)al?RuL7tOO z->;I}>%WI{;vbLP3VIQ^iA$4wl6@0sDj|~112Y4OFjMs`13!$JGkp%b&E8QzJw_L5 zOnw9joc0^;O%OpF$Qp)W1HI!$4BaXX84`%@#^dk^hFp^pQ@rx4g(8Xjy#!X%+X5Jd@fs3amGT`}mhq#L97R>OwT5-m|h#yT_-v@(k$q7P*9X~T*3)LTdzP!*B} z+SldbVWrrwQo9wX*%FyK+sRXTa@O?WM^FGWOE?S`R(0P{<6p#f?0NJvnBia?k^fX2 zNQs7K-?EijgHJY}&zsr;qJ<*PCZUd*x|dD=IQPUK_nn)@X4KWtqoJNHkT?ZWL_hF? zS8lp2(q>;RXR|F;1O}EE#}gCrY~#n^O`_I&?&z5~7N;zL0)3Tup`%)oHMK-^r$NT% zbFg|o?b9w(q@)6w5V%si<$!U<#}s#x@0aX-hP>zwS#9*75VXA4K*%gUc>+yzupTDBOKH8WR4V0pM(HrfbQ&eJ79>HdCvE=F z|J>s;;iDLB^3(9}?biKbxf1$lI!*Z%*0&8UUq}wMyPs_hclyQQi4;NUY+x2qy|0J; zhn8;5)4ED1oHwg+VZF|80<4MrL97tGGXc5Sw$wAI#|2*cvQ=jB5+{AjMiDHmhUC*a zlmiZ`LAuAn_}hftXh;`Kq0zblDk8?O-`tnilIh|;3lZp@F_osJUV9`*R29M?7H{Fy z`nfVEIDIWXmU&YW;NjU8)EJpXhxe5t+scf|VXM!^bBlwNh)~7|3?fWwo_~ZFk(22% zTMesYw+LNx3J-_|DM~`v93yXe=jPD{q;li;5PD?Dyk+b? zo21|XpT@)$BM$%F=P9J19Vi&1#{jM3!^Y&fr&_`toi`XB1!n>sbL%U9I5<7!@?t)~ z;&H%z>bAaQ4f$wIzkjH70;<8tpUoxzKrPhn#IQfS%9l5=Iu))^XC<58D!-O z{B+o5R^Z21H0T9JQ5gNJnqh#qH^na|z92=hONIM~@_iuOi|F>jBh-?aA20}Qx~EpDGElELNn~|7WRXRFnw+Wdo`|# zBpU=Cz3z%cUJ0mx_1($X<40XEIYz(`noWeO+x#yb_pwj6)R(__%@_Cf>txOQ74wSJ z0#F3(zWWaR-jMEY$7C*3HJrohc79>MCUu26mfYN)f4M~4gD`}EX4e}A!U}QV8!S47 z6y-U-%+h`1n`*pQuKE%Av0@)+wBZr9mH}@vH@i{v(m-6QK7Ncf17x_D=)32`FOjjo zg|^VPf5c6-!FxN{25dvVh#fog=NNpXz zfB$o+0jbRkHH{!TKhE709f+jI^$3#v1Nmf80w`@7-5$1Iv_`)W^px8P-({xwb;D0y z7LKDAHgX<84?l!I*Dvi2#D@oAE^J|g$3!)x1Ua;_;<@#l1fD}lqU2_tS^6Ht$1Wl} zBESo7o^)9-Tjuz$8YQSGhfs{BQV6zW7dA?0b(Dbt=UnQs&4zHfe_sj{RJ4uS-vQpC zX;Bbsuju4%!o8?&m4UZU@~ZZjeFF6ex2ss5_60_JS_|iNc+R0GIjH1@Z z=rLT9%B|WWgOrR7IiIwr2=T;Ne?30M!@{%Qf8o`!>=s<2CBpCK_TWc(DX51>e^xh8 z&@$^b6CgOd7KXQV&Y4%}_#uN*mbanXq(2=Nj`L7H7*k(6F8s6{FOw@(DzU`4-*77{ zF+dxpv}%mFpYK?>N_2*#Y?oB*qEKB}VoQ@bzm>ptmVS_EC(#}Lxxx730trt0G)#$b zE=wVvtqOct1%*9}U{q<)2?{+0TzZzP0jgf9*)arV)*e!f`|jgT{7_9iS@e)recI#z zbzolURQ+TOzE!ymqvBY7+5NnAbWxvMLsLTwEbFqW=CPyCsmJ}P1^V30|D5E|p3BC5 z)3|qgw@ra7aXb-wsa|l^in~1_fm{7bS9jhVRkYVO#U{qMp z)Wce+|DJ}4<2gp8r0_xfZpMo#{Hl2MfjLcZdRB9(B(A(f;+4s*FxV{1F|4d`*sRNd zp4#@sEY|?^FIJ;tmH{@keZ$P(sLh5IdOk@k^0uB^BWr@pk6mHy$qf&~rI>P*a;h0C{%oA*i!VjWn&D~O#MxN&f@1Po# zKN+ zrGrkSjcr?^R#nGl<#Q722^wbYcgW@{+6CBS<1@%dPA8HC!~a`jTz<`g_l5N1M@9wn9GOAZ>nqNgq!yOCbZ@1z`U_N`Z>}+1HIZxk*5RDc&rd5{3qjRh8QmT$VyS;jK z;AF+r6XnnCp=wQYoG|rT2@8&IvKq*IB_WvS%nt%e{MCFm`&W*#LXc|HrD?nVBo=(8*=Aq?u$sDA_sC_RPDUiQ+wnIJET8vx$&fxkW~kP9qXKt zozR)@xGC!P)CTkjeWvXW5&@2?)qt)jiYWWBU?AUtzAN}{JE1I)dfz~7$;}~BmQF`k zpn11qmObXwRB8&rnEG*#4Xax3XBkKlw(;tb?Np^i+H8m(Wyz9k{~ogba@laiEk;2! zV*QV^6g6(QG%vX5Um#^sT&_e`B1pBW5yVth~xUs#0}nv?~C#l?W+9Lsb_5)!71rirGvY zTIJ$OPOY516Y|_014sNv+Z8cc5t_V=i>lWV=vNu#!58y9Zl&GsMEW#pPYPYGHQ|;vFvd*9eM==$_=vc7xnyz0~ zY}r??$<`wAO?JQk@?RGvkWVJlq2dk9vB(yV^vm{=NVI8dhsX<)O(#nr9YD?I?(VmQ z^r7VfUBn<~p3()8yOBjm$#KWx!5hRW)5Jl7wY@ky9lNM^jaT##8QGVsYeaVywmpv>X|Xj7gWE1Ezai&wVLt3p)k4w~yrskT-!PR!kiyQlaxl(( zXhF%Q9x}1TMt3~u@|#wWm-Vq?ZerK={8@~&@9r5JW}r#45#rWii};t`{5#&3$W)|@ zbAf2yDNe0q}NEUvq_Quq3cTjcw z@H_;$hu&xllCI9CFDLuScEMg|x{S7GdV8<&Mq=ezDnRZAyX-8gv97YTm0bg=d)(>N z+B2FcqvI9>jGtnK%eO%y zoBPkJTk%y`8TLf4)IXPBn`U|9>O~WL2C~C$z~9|0m*YH<-vg2CD^SX#&)B4ngOSG$ zV^wmy_iQk>dfN@Pv(ckfy&#ak@MLC7&Q6Ro#!ezM*VEh`+b3Jt%m(^T&p&WJ2Oqvj zs-4nq0TW6cv~(YI$n0UkfwN}kg3_fp?(ijSV#tR9L0}l2qjc7W?i*q01=St0eZ=4h zyGQbEw`9OEH>NMuIe)hVwYHsGERWOD;JxEiO7cQv%pFCeR+IyhwQ|y@&^24k+|8fD zLiOWFNJ2&vu2&`Jv96_z-Cd5RLgmeY3*4rDOQo?Jm`;I_(+ejsPM03!ly!*Cu}Cco zrQSrEDHNyzT(D5s1rZq!8#?f6@v6dB7a-aWs(Qk>N?UGAo{gytlh$%_IhyL7h?DLXDGx zgxGEBQoCAWo-$LRvM=F5MTle`M})t3vVv;2j0HZY&G z22^iGhV@uaJh(XyyY%} zd4iH_UfdV#T=3n}(Lj^|n;O4|$;xhu*8T3hR1mc_A}fK}jfZ7LX~*n5+`8N2q#rI$ z@<_2VANlYF$vIH$ zl<)+*tIWW78IIINA7Rr7i{<;#^yzxoLNkXL)eSs=%|P>$YQIh+ea_3k z_s7r4%j7%&*NHSl?R4k%1>Z=M9o#zxY!n8sL5>BO-ZP;T3Gut>iLS@U%IBrX6BA3k z)&@q}V8a{X<5B}K5s(c(LQ=%v1ocr`t$EqqY0EqVjr65usa=0bkf|O#ky{j3)WBR(((L^wmyHRzoWuL2~WTC=`yZ zn%VX`L=|Ok0v7?s>IHg?yArBcync5rG#^+u)>a%qjES%dRZoIyA8gQ;StH z1Ao7{<&}6U=5}4v<)1T7t!J_CL%U}CKNs-0xWoTTeqj{5{?Be$L0_tk>M9o8 zo371}S#30rKZFM{`H_(L`EM9DGp+Mifk&IP|C2Zu_)Ghr4Qtpmkm1osCf@%Z$%t+7 zYH$Cr)Ro@3-QDeQJ8m+x6%;?YYT;k6Z0E-?kr>x33`H%*ueBD7Zx~3&HtWn0?2Wt} zTG}*|v?{$ajzt}xPzV%lL1t-URi8*Zn)YljXNGDb>;!905Td|mpa@mHjIH%VIiGx- zd@MqhpYFu4_?y5N4xiHn3vX&|e6r~Xt> zZG`aGq|yTNjv;9E+Txuoa@A(9V7g?1_T5FzRI;!=NP1Kqou1z5?%X~Wwb{trRfd>i z8&y^H)8YnKyA_Fyx>}RNmQIczT?w2J4SNvI{5J&}Wto|8FR(W;Qw#b1G<1%#tmYzQ zQ2mZA-PAdi%RQOhkHy9Ea#TPSw?WxwL@H@cbkZwIq0B!@ns}niALidmn&W?!Vd4Gj zO7FiuV4*6Mr^2xlFSvM;Cp_#r8UaqIzHJQg_z^rEJw&OMm_8NGAY2)rKvki|o1bH~ z$2IbfVeY2L(^*rMRU1lM5Y_sgrDS`Z??nR2lX;zyR=c%UyGb*%TC-Dil?SihkjrQy~TMv6;BMs7P8il`H7DmpVm@rJ;b)hW)BL)GjS154b*xq-NXq2cwE z^;VP7ua2pxvCmxrnqUYQMH%a%nHmwmI33nJM(>4LznvY*k&C0{8f*%?zggpDgkuz&JBx{9mfb@wegEl2v!=}Sq2Gaty0<)UrOT0{MZtZ~j5y&w zXlYa_jY)I_+VA-^#mEox#+G>UgvM!Ac8zI<%JRXM_73Q!#i3O|)lOP*qBeJG#BST0 zqohi)O!|$|2SeJQo(w6w7%*92S})XfnhrH_Z8qe!G5>CglP=nI7JAOW?(Z29;pXJ9 zR9`KzQ=WEhy*)WH>$;7Cdz|>*i>=##0bB)oU0OR>>N<21e4rMCHDemNi2LD>Nc$;& zQRFthpWniC1J6@Zh~iJCoLOxN`oCKD5Q4r%ynwgUKPlIEd#?QViIqovY|czyK8>6B zSP%{2-<;%;1`#0mG^B(8KbtXF;Nf>K#Di72UWE4gQ%(_26Koiad)q$xRL~?pN71ZZ zujaaCx~jXjygw;rI!WB=xrOJO6HJ!!w}7eiivtCg5K|F6$EXa)=xUC za^JXSX98W`7g-tm@uo|BKj39Dl;sg5ta;4qjo^pCh~{-HdLl6qI9Ix6f$+qiZ$}s= zNguKrU;u+T@ko(Vr1>)Q%h$?UKXCY>3se%&;h2osl2D zE4A9bd7_|^njDd)6cI*FupHpE3){4NQ*$k*cOWZ_?CZ>Z4_fl@n(mMnYK62Q1d@+I zr&O))G4hMihgBqRIAJkLdk(p(D~X{-oBUA+If@B}j& zsHbeJ3RzTq96lB7d($h$xTeZ^gP0c{t!Y0c)aQE;$FY2!mACg!GDEMKXFOPI^)nHZ z`aSPJpvV0|bbrzhWWkuPURlDeN%VT8tndV8?d)eN*i4I@u zVKl^6{?}A?P)Fsy?3oi#clf}L18t;TjNI2>eI&(ezDK7RyqFxcv%>?oxUlonv(px) z$vnPzRH`y5A(x!yOIfL0bmgeMQB$H5wenx~!ujQK*nUBW;@Em&6Xv2%s(~H5WcU2R z;%Nw<$tI)a`Ve!>x+qegJnQsN2N7HaKzrFqM>`6R*gvh%O*-%THt zrB$Nk;lE;z{s{r^PPm5qz(&lM{sO*g+W{sK+m3M_z=4=&CC>T`{X}1Vg2PEfSj2x_ zmT*(x;ov%3F?qoEeeM>dUn$a*?SIGyO8m806J1W1o+4HRhc2`9$s6hM#qAm zChQ87b~GEw{ADfs+5}FJ8+|bIlIv(jT$Ap#hSHoXdd9#w<#cA<1Rkq^*EEkknUd4& zoIWIY)sAswy6fSERVm&!SO~#iN$OgOX*{9@_BWFyJTvC%S++ilSfCrO(?u=Dc?CXZ zzCG&0yVR{Z`|ZF0eEApWEo#s9osV>F{uK{QA@BES#&;#KsScf>y zvs?vIbI>VrT<*!;XmQS=bhq%46-aambZ(8KU-wOO2=en~D}MCToB_u;Yz{)1ySrPZ z@=$}EvjTdzTWU7c0ZI6L8=yP+YRD_eMMos}b5vY^S*~VZysrkq<`cK3>>v%uy7jgq z0ilW9KjVDHLv0b<1K_`1IkbTOINs0=m-22c%M~l=^S}%hbli-3?BnNq?b`hx^HX2J zIe6ECljRL0uBWb`%{EA=%!i^4sMcj+U_TaTZRb+~GOk z^ZW!nky0n*Wb*r+Q|9H@ml@Z5gU&W`(z4-j!OzC1wOke`TRAYGZVl$PmQ16{3196( zO*?`--I}Qf(2HIwb2&1FB^!faPA2=sLg(@6P4mN)>Dc3i(B0;@O-y2;lM4akD>@^v z=u>*|!s&9zem70g7zfw9FXl1bpJW(C#5w#uy5!V?Q(U35A~$dR%LDVnq@}kQm13{} zd53q3N(s$Eu{R}k2esbftfjfOITCL;jWa$}(mmm}d(&7JZ6d3%IABCapFFYjdEjdK z&4Edqf$G^MNAtL=uCDRs&Fu@FXRgX{*0<(@c3|PNHa>L%zvxWS={L8%qw`STm+=Rd zA}FLspESSIpE_^41~#5yI2bJ=9`oc;GIL!JuW&7YetZ?0H}$$%8rW@*J37L-~Rsx!)8($nI4 zZhcZ2^=Y+p4YPl%j!nFJA|*M^gc(0o$i3nlphe+~-_m}jVkRN{spFs(o0ajW@f3K{ zDV!#BwL322CET$}Y}^0ixYj2w>&Xh12|R8&yEw|wLDvF!lZ#dOTHM9pK6@Nm-@9Lnng4ZHBgBSrr7KI8YCC9DX5Kg|`HsiwJHg2(7#nS;A{b3tVO?Z% za{m5b3rFV6EpX;=;n#wltDv1LE*|g5pQ+OY&*6qCJZc5oDS6Z6JD#6F)bWxZSF@q% z+1WV;m!lRB!n^PC>RgQCI#D1br_o^#iPk>;K2hB~0^<~)?p}LG%kigm@moD#q3PE+ zA^Qca)(xnqw6x>XFhV6ku9r$E>bWNrVH9fum0?4s?Rn2LG{Vm_+QJHse6xa%nzQ?k zKug4PW~#Gtb;#5+9!QBgyB@q=sk9=$S{4T>wjFICStOM?__fr+Kei1 z3j~xPqW;W@YkiUM;HngG!;>@AITg}vAE`M2Pj9Irl4w1fo4w<|Bu!%rh%a(Ai^Zhi zs92>v5;@Y(Zi#RI*ua*h`d_7;byQSa*v9E{2x$<-_=5Z<7{%)}4XExANcz@rK69T0x3%H<@frW>RA8^swA+^a(FxK| zFl3LD*ImHN=XDUkrRhp6RY5$rQ{bRgSO*(vEHYV)3Mo6Jy3puiLmU&g82p{qr0F?ohmbz)f2r{X2|T2 z$4fdQ=>0BeKbiVM!e-lIIs8wVTuC_m7}y4A_%ikI;Wm5$9j(^Y z(cD%U%k)X>_>9~t8;pGzL6L-fmQO@K; zo&vQzMlgY95;1BSkngY)e{`n0!NfVgf}2mB3t}D9@*N;FQ{HZ3Pb%BK6;5#-O|WI( zb6h@qTLU~AbVW#_6?c!?Dj65Now7*pU{h!1+eCV^KCuPAGs28~3k@ueL5+u|Z-7}t z9|lskE`4B7W8wMs@xJa{#bsCGDFoRSNSnmNYB&U7 zVGKWe%+kFB6kb)e;TyHfqtU6~fRg)f|>=5(N36)0+C z`hv65J<$B}WUc!wFAb^QtY31yNleq4dzmG`1wHTj=c*=hay9iD071Hc?oYoUk|M*_ zU1GihAMBsM@5rUJ(qS?9ZYJ6@{bNqJ`2Mr+5#hKf?doa?F|+^IR!8lq9)wS3tF_9n zW_?hm)G(M+MYb?V9YoX^_mu5h-LP^TL^!Q9Z7|@sO(rg_4+@=PdI)WL(B7`!K^ND- z-uIuVDCVEdH_C@c71YGYT^_Scf_dhB8Z2Xy6vGtBSlYud9vggOqv^L~F{BraSE_t} zIkP+Hp2&nH^-MNEs}^`oMLy11`PQW$T|K(`Bu*(f@)mv1-qY(_YG&J2M2<7k;;RK~ zL{Fqj9yCz8(S{}@c)S!65aF<=&eLI{hAMErCx&>i7OeDN>okvegO87OaG{Jmi<|}D zaT@b|0X{d@OIJ7zvT>r+eTzgLq~|Dpu)Z&db-P4z*`M$UL51lf>FLlq6rfG)%doyp z)3kk_YIM!03eQ8Vu_2fg{+osaEJPtJ-s36R+5_AEG12`NG)IQ#TF9c@$99%0iye+ zUzZ57=m2)$D(5Nx!n)=5Au&O0BBgwxIBaeI(mro$#&UGCr<;C{UjJVAbVi%|+WP(a zL$U@TYCxJ=1{Z~}rnW;7UVb7+ZnzgmrogDxhjLGo>c~MiJAWs&&;AGg@%U?Y^0JhL ze(x6Z74JG6FlOFK(T}SXQfhr}RIFl@QXKnIcXYF)5|V~e-}suHILKT-k|<*~Ij|VF zC;t@=uj=hot~*!C68G8hTA%8SzOfETOXQ|3FSaIEjvBJp(A)7SWUi5!Eu#yWgY+;n zlm<$+UDou*V+246_o#V4kMdto8hF%%Lki#zPh}KYXmMf?hrN0;>Mv%`@{0Qn`Ujp) z=lZe+13>^Q!9zT);H<(#bIeRWz%#*}sgUX9P|9($kexOyKIOc`dLux}c$7It4u|Rl z6SSkY*V~g_B-hMPo_ak>>z@AVQ(_N)VY2kB3IZ0G(iDUYw+2d7W^~(Jq}KY=JnWS( z#rzEa&0uNhJ>QE8iiyz;n2H|SV#Og+wEZv=f2%1ELX!SX-(d3tEj$5$1}70Mp<&eI zCkfbByL7af=qQE@5vDVxx1}FSGt_a1DoE3SDI+G)mBAna)KBG4p8Epxl9QZ4BfdAN zFnF|Y(umr;gRgG6NLQ$?ZWgllEeeq~z^ZS7L?<(~O&$5|y)Al^iMKy}&W+eMm1W z7EMU)u^ke(A1#XCV>CZ71}P}0x)4wtHO8#JRG3MA-6g=`ZM!FcICCZ{IEw8Dm2&LQ z1|r)BUG^0GzI6f946RrBlfB1Vs)~8toZf~7)+G;pv&XiUO(%5bm)pl=p>nV^o*;&T z;}@oZSibzto$arQgfkp|z4Z($P>dTXE{4O=vY0!)kDO* zGF8a4wq#VaFpLfK!iELy@?-SeRrdz%F*}hjKcA*y@mj~VD3!it9lhRhX}5YOaR9$} z3mS%$2Be7{l(+MVx3 z(4?h;P!jnRmX9J9sYN#7i=iyj_5q7n#X(!cdqI2lnr8T$IfOW<_v`eB!d9xY1P=2q&WtOXY=D9QYteP)De?S4}FK6#6Ma z=E*V+#s8>L;8aVroK^6iKo=MH{4yEZ_>N-N z`(|;aOATba1^asjxlILk<4}f~`39dBFlxj>Dw(hMYKPO3EEt1@S`1lxFNM+J@uB7T zZ8WKjz7HF1-5&2=l=fqF-*@>n5J}jIxdDwpT?oKM3s8Nr`x8JnN-kCE?~aM1H!hAE z%%w(3kHfGwMnMmNj(SU(w42OrC-euI>Dsjk&jz3ts}WHqmMpzQ3vZrsXrZ|}+MHA7 z068obeXZTsO*6RS@o3x80E4ok``rV^Y3hr&C1;|ZZ0|*EKO`$lECUYG2gVFtUTw)R z4Um<0ZzlON`zTdvVdL#KFoMFQX*a5wM0Czp%wTtfK4Sjs)P**RW&?lP$(<}q%r68Z zS53Y!d@&~ne9O)A^tNrXHhXBkj~$8j%pT1%%mypa9AW5E&s9)rjF4@O3ytH{0z6riz|@< zB~UPh*wRFg2^7EbQrHf0y?E~dHlkOxof_a?M{LqQ^C!i2dawHTPYUE=X@2(3<=OOxs8qn_(y>pU>u^}3y&df{JarR0@VJn0f+U%UiF=$Wyq zQvnVHESil@d|8&R<%}uidGh7@u^(%?$#|&J$pvFC-n8&A>utA=n3#)yMkz+qnG3wd zP7xCnF|$9Dif@N~L)Vde3hW8W!UY0BgT2v(wzp;tlLmyk2%N|0jfG$%<;A&IVrOI< z!L)o>j>;dFaqA3pL}b-Je(bB@VJ4%!JeX@3x!i{yIeIso^=n?fDX`3bU=eG7sTc%g%ye8$v8P@yKE^XD=NYxTb zbf!Mk=h|otpqjFaA-vs5YOF-*GwWPc7VbaOW&stlANnCN8iftFMMrUdYNJ_Bnn5Vt zxfz@Ah|+4&P;reZxp;MmEI7C|FOv8NKUm8njF7Wb6Gi7DeODLl&G~}G4be&*Hi0Qw z5}77vL0P+7-B%UL@3n1&JPxW^d@vVwp?u#gVcJqY9#@-3X{ok#UfW3<1fb%FT`|)V~ggq z(3AUoUS-;7)^hCjdT0Kf{i}h)mBg4qhtHHBti=~h^n^OTH5U*XMgDLIR@sre`AaB$ zg)IGBET_4??m@cx&c~bA80O7B8CHR7(LX7%HThkeC*@vi{-pL%e)yXp!B2InafbDF zjPXf1mko3h59{lT6EEbxKO1Z5GF71)WwowO6kY|6tjSVSWdQ}NsK2x{>i|MKZK8%Q zfu&_0D;CO-Jg0#YmyfctyJ!mRJp)e#@O0mYdp|8x;G1%OZQ3Q847YWTyy|%^cpA;m zze0(5p{tMu^lDkpe?HynyO?a1$_LJl2L&mpeKu%8YvgRNr=%2z${%WThHG=vrWY@4 zsA`OP#O&)TetZ>s%h!=+CE15lOOls&nvC~$Qz0Ph7tHiP;O$i|eDwpT{cp>+)0-|; zY$|bB+Gbel>5aRN3>c0x)4U=|X+z+{ zn*_p*EQoquRL+=+p;=lm`d71&1NqBz&_ph)MXu(Nv6&XE7(RsS)^MGj5Q?Fwude-(sq zjJ>aOq!7!EN>@(fK7EE#;i_BGvli`5U;r!YA{JRodLBc6-`n8K+Fjgwb%sX;j=qHQ z7&Tr!)!{HXoO<2BQrV9Sw?JRaLXV8HrsNevvnf>Y-6|{T!pYLl7jp$-nEE z#X!4G4L#K0qG_4Z;Cj6=;b|Be$hi4JvMH!-voxqx^@8cXp`B??eFBz2lLD8RRaRGh zn7kUfy!YV~p(R|p7iC1Rdgt$_24i0cd-S8HpG|`@my70g^y`gu%#Tf_L21-k?sRRZHK&at(*ED0P8iw{7?R$9~OF$Ko;Iu5)ur5<->x!m93Eb zFYpIx60s=Wxxw=`$aS-O&dCO_9?b1yKiPCQmSQb>T)963`*U+Ydj5kI(B(B?HNP8r z*bfSBpSu)w(Z3j7HQoRjUG(+d=IaE~tv}y14zHHs|0UcN52fT8V_<@2ep_ee{QgZG zmgp8iv4V{k;~8@I%M3<#B;2R>Ef(Gg_cQM7%}0s*^)SK6!Ym+~P^58*wnwV1BW@eG z4sZLqsUvBbFsr#8u7S1r4teQ;t)Y@jnn_m5jS$CsW1um!p&PqAcc8!zyiXHVta9QC zY~wCwCF0U%xiQPD_INKtTb;A|Zf29(mu9NI;E zc-e>*1%(LSXB`g}kd`#}O;veb<(sk~RWL|f3ljxCnEZDdNSTDV6#Td({6l&y4IjKF z^}lIUq*ZUqgTPumD)RrCN{M^jhY>E~1pn|KOZ5((%F)G|*ZQ|r4zIbrEiV%42hJV8 z3xS)=!X1+=olbdGJ=yZil?oXLct8FM{(6ikLL3E%=q#O6(H$p~gQu6T8N!plf!96| z&Q3=`L~>U0zZh;z(pGR2^S^{#PrPxTRHD1RQOON&f)Siaf`GLj#UOk&(|@0?zm;Sx ztsGt8=29-MZs5CSf1l1jNFtNt5rFNZxJPvkNu~2}7*9468TWm>nN9TP&^!;J{-h)_ z7WsHH9|F%I`Pb!>KAS3jQWKfGivTVkMJLO-HUGM_a4UQ_%RgL6WZvrW+Z4ujZn;y@ zz9$=oO!7qVTaQAA^BhX&ZxS*|5dj803M=k&2%QrXda`-Q#IoZL6E(g+tN!6CA!CP* zCpWtCujIea)ENl0liwVfj)Nc<9mV%+e@=d`haoZ*`B7+PNjEbXBkv=B+Pi^~L#EO$D$ZqTiD8f<5$eyb54-(=3 zh)6i8i|jp(@OnRrY5B8t|LFXFQVQ895n*P16cEKTrT*~yLH6Z4e*bZ5otpRDri&+A zfNbK1D5@O=sm`fN=WzWyse!za5n%^+6dHPGX#8DyIK>?9qyX}2XvBWVqbP%%D)7$= z=#$WulZlZR<{m#gU7lwqK4WS1Ne$#_P{b17qe$~UOXCl>5b|6WVh;5vVnR<%d+Lnp z$uEmML38}U4vaW8>shm6CzB(Wei3s#NAWE3)a2)z@i{4jTn;;aQS)O@l{rUM`J@K& l00vQ5JBs~;vo!vr%%-k{2_Fq1Mn4QF81S)AQ99zk{{c4yR+0b! literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..1af9e09 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..1aa94a4 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..93e3f59 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..ebf1ef8 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'spring' diff --git a/src/main/java/friend/spring/Application.java b/src/main/java/friend/spring/Application.java new file mode 100644 index 0000000..26c141d --- /dev/null +++ b/src/main/java/friend/spring/Application.java @@ -0,0 +1,13 @@ +package friend.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/src/test/java/friend/spring/ApplicationTests.java b/src/test/java/friend/spring/ApplicationTests.java new file mode 100644 index 0000000..9ba171d --- /dev/null +++ b/src/test/java/friend/spring/ApplicationTests.java @@ -0,0 +1,13 @@ +package friend.spring; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ApplicationTests { + + @Test + void contextLoads() { + } + +} From e7af8c6607678d8480bf3811518e0ae3f4b11a7c Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 18 Jan 2024 14:41:59 +0900 Subject: [PATCH 002/255] =?UTF-8?q?Feat:=20=EC=8A=A4=ED=94=84=EB=A7=81?= =?UTF-8?q?=EB=B6=80=ED=8A=B8=20=EA=B8=B0=EB=B3=B8=20=EC=84=B8=ED=8C=85=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 +- src/main/java/friend/spring/Application.java | 2 + .../friend/spring/apiPayload/ApiResponse.java | 39 +++++++ .../spring/apiPayload/code/BaseCode.java | 8 ++ .../spring/apiPayload/code/BaseErrorCode.java | 8 ++ .../apiPayload/code/ErrorReasonDTO.java | 14 +++ .../spring/apiPayload/code/ReasonDTO.java | 14 +++ .../apiPayload/code/status/ErrorStatus.java | 48 ++++++++ .../apiPayload/code/status/SuccessStatus.java | 44 ++++++++ .../spring/converter/UserConverter.java | 4 + src/main/java/friend/spring/domain/Alarm.java | 32 ++++++ .../java/friend/spring/domain/Comment.java | 47 ++++++++ .../friend/spring/domain/Gauge_question.java | 33 ++++++ .../java/friend/spring/domain/Gauge_vote.java | 27 +++++ .../spring/domain/General_question.java | 86 +++++++++++++++ .../friend/spring/domain/General_vote.java | 54 +++++++++ src/main/java/friend/spring/domain/Level.java | 28 +++++ src/main/java/friend/spring/domain/Point.java | 26 +++++ src/main/java/friend/spring/domain/Post.java | 94 ++++++++++++++++ .../java/friend/spring/domain/Report.java | 37 +++++++ src/main/java/friend/spring/domain/User.java | 104 ++++++++++++++++++ .../spring/domain/common/BaseEntity.java | 25 +++++ .../friend/spring/domain/enums/AlarmType.java | 5 + .../friend/spring/domain/enums/Gender.java | 5 + .../friend/spring/domain/enums/PostState.java | 5 + .../friend/spring/domain/enums/PostType.java | 5 + .../spring/domain/enums/PostVoteType.java | 5 + .../spring/domain/enums/ReportCategory.java | 5 + .../spring/domain/enums/ReportType.java | 5 + .../spring/domain/mapping/Comment_choice.java | 29 +++++ .../spring/domain/mapping/Comment_like.java | 28 +++++ .../spring/domain/mapping/Post_like.java | 26 +++++ .../spring/domain/mapping/Post_scrap.java | 26 +++++ .../spring/repository/UserRepository.java | 7 ++ .../friend/spring/service/UserService.java | 4 + .../spring/service/UserServiceImpl.java | 9 ++ .../web/controller/UserRestController.java | 12 ++ .../friend/spring/web/dto/UserRequestDTO.java | 4 + .../spring/web/dto/UserResponseDTO.java | 4 + src/main/resources/application.properties | 1 - src/main/resources/application.yml | 20 ++++ 41 files changed, 980 insertions(+), 3 deletions(-) create mode 100644 src/main/java/friend/spring/apiPayload/ApiResponse.java create mode 100644 src/main/java/friend/spring/apiPayload/code/BaseCode.java create mode 100644 src/main/java/friend/spring/apiPayload/code/BaseErrorCode.java create mode 100644 src/main/java/friend/spring/apiPayload/code/ErrorReasonDTO.java create mode 100644 src/main/java/friend/spring/apiPayload/code/ReasonDTO.java create mode 100644 src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java create mode 100644 src/main/java/friend/spring/apiPayload/code/status/SuccessStatus.java create mode 100644 src/main/java/friend/spring/converter/UserConverter.java create mode 100644 src/main/java/friend/spring/domain/Alarm.java create mode 100644 src/main/java/friend/spring/domain/Comment.java create mode 100644 src/main/java/friend/spring/domain/Gauge_question.java create mode 100644 src/main/java/friend/spring/domain/Gauge_vote.java create mode 100644 src/main/java/friend/spring/domain/General_question.java create mode 100644 src/main/java/friend/spring/domain/General_vote.java create mode 100644 src/main/java/friend/spring/domain/Level.java create mode 100644 src/main/java/friend/spring/domain/Point.java create mode 100644 src/main/java/friend/spring/domain/Post.java create mode 100644 src/main/java/friend/spring/domain/Report.java create mode 100644 src/main/java/friend/spring/domain/User.java create mode 100644 src/main/java/friend/spring/domain/common/BaseEntity.java create mode 100644 src/main/java/friend/spring/domain/enums/AlarmType.java create mode 100644 src/main/java/friend/spring/domain/enums/Gender.java create mode 100644 src/main/java/friend/spring/domain/enums/PostState.java create mode 100644 src/main/java/friend/spring/domain/enums/PostType.java create mode 100644 src/main/java/friend/spring/domain/enums/PostVoteType.java create mode 100644 src/main/java/friend/spring/domain/enums/ReportCategory.java create mode 100644 src/main/java/friend/spring/domain/enums/ReportType.java create mode 100644 src/main/java/friend/spring/domain/mapping/Comment_choice.java create mode 100644 src/main/java/friend/spring/domain/mapping/Comment_like.java create mode 100644 src/main/java/friend/spring/domain/mapping/Post_like.java create mode 100644 src/main/java/friend/spring/domain/mapping/Post_scrap.java create mode 100644 src/main/java/friend/spring/repository/UserRepository.java create mode 100644 src/main/java/friend/spring/service/UserService.java create mode 100644 src/main/java/friend/spring/service/UserServiceImpl.java create mode 100644 src/main/java/friend/spring/web/controller/UserRestController.java create mode 100644 src/main/java/friend/spring/web/dto/UserRequestDTO.java create mode 100644 src/main/java/friend/spring/web/dto/UserResponseDTO.java delete mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/application.yml diff --git a/build.gradle b/build.gradle index 8a268e6..ad10e0b 100644 --- a/build.gradle +++ b/build.gradle @@ -22,10 +22,10 @@ repositories { } dependencies { -// implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' -// runtimeOnly 'com.mysql:mysql-connector-j' + runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/src/main/java/friend/spring/Application.java b/src/main/java/friend/spring/Application.java index 26c141d..401acbc 100644 --- a/src/main/java/friend/spring/Application.java +++ b/src/main/java/friend/spring/Application.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @SpringBootApplication +@EnableJpaAuditing public class Application { public static void main(String[] args) { diff --git a/src/main/java/friend/spring/apiPayload/ApiResponse.java b/src/main/java/friend/spring/apiPayload/ApiResponse.java new file mode 100644 index 0000000..df8989f --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/ApiResponse.java @@ -0,0 +1,39 @@ +package friend.spring.apiPayload; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import friend.spring.apiPayload.code.BaseCode; +import friend.spring.apiPayload.code.status.SuccessStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@JsonPropertyOrder({"isSuccess", "code", "message", "result"}) +public class ApiResponse { + + @JsonProperty("isSuccess") + private final Boolean isSuccess; + private final String code; + private final String message; + @JsonInclude(JsonInclude.Include.NON_NULL) + private T result; + + + // 성공한 경우 응답 생성 + + public static ApiResponse onSuccess(T result){ + return new ApiResponse<>(true, SuccessStatus._OK.getCode() , SuccessStatus._OK.getMessage(), result); + } + + public static ApiResponse of(BaseCode code, T result){ + return new ApiResponse<>(true, code.getReasonHttpStatus().getCode() , code.getReasonHttpStatus().getMessage(), result); + } + + + // 실패한 경우 응답 생성 + public static ApiResponse onFailure(String code, String message, T data){ + return new ApiResponse<>(false, code, message, data); + } +} diff --git a/src/main/java/friend/spring/apiPayload/code/BaseCode.java b/src/main/java/friend/spring/apiPayload/code/BaseCode.java new file mode 100644 index 0000000..064d788 --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/code/BaseCode.java @@ -0,0 +1,8 @@ +package friend.spring.apiPayload.code; + +public interface BaseCode { + + public ReasonDTO getReason(); + + public ReasonDTO getReasonHttpStatus(); +} \ No newline at end of file diff --git a/src/main/java/friend/spring/apiPayload/code/BaseErrorCode.java b/src/main/java/friend/spring/apiPayload/code/BaseErrorCode.java new file mode 100644 index 0000000..3d8b1eb --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/code/BaseErrorCode.java @@ -0,0 +1,8 @@ +package friend.spring.apiPayload.code; + +public interface BaseErrorCode { + + public ErrorReasonDTO getReason(); + + public ErrorReasonDTO getReasonHttpStatus(); +} \ No newline at end of file diff --git a/src/main/java/friend/spring/apiPayload/code/ErrorReasonDTO.java b/src/main/java/friend/spring/apiPayload/code/ErrorReasonDTO.java new file mode 100644 index 0000000..3c805fc --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/code/ErrorReasonDTO.java @@ -0,0 +1,14 @@ +package friend.spring.apiPayload.code; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Builder +@Getter +public class ErrorReasonDTO { + private final HttpStatus httpStatus; + private final String code; + private final String message; + private final boolean isSuccess; +} diff --git a/src/main/java/friend/spring/apiPayload/code/ReasonDTO.java b/src/main/java/friend/spring/apiPayload/code/ReasonDTO.java new file mode 100644 index 0000000..c48f905 --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/code/ReasonDTO.java @@ -0,0 +1,14 @@ +package friend.spring.apiPayload.code; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Builder +@Getter +public class ReasonDTO { + private final HttpStatus httpStatus; + private final String code; + private final String message; + private final boolean isSuccess; +} \ No newline at end of file diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java new file mode 100644 index 0000000..8c9e09f --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -0,0 +1,48 @@ +package friend.spring.apiPayload.code.status; + +import friend.spring.apiPayload.code.BaseErrorCode; +import friend.spring.apiPayload.code.ErrorReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum ErrorStatus implements BaseErrorCode { + + // 가장 일반적인 응답 + _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버 에러, 관리자에게 문의 바랍니다."), + _BAD_REQUEST(HttpStatus.BAD_REQUEST,"COMMON400","잘못된 요청입니다."), + _UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON401","인증이 필요합니다."), + _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."), + ; + + // 멤버 관련 응답 + + // ~~~ 관련 응답 .... + + private final HttpStatus httpStatus; + private final String code; + private final String message; + + @Override + public ErrorReasonDTO getReason() { + return ErrorReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(false) + .build(); + } + + @Override + public ErrorReasonDTO getReasonHttpStatus() { + return ErrorReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(false) + .httpStatus(httpStatus) + .build() + ; + } +} + diff --git a/src/main/java/friend/spring/apiPayload/code/status/SuccessStatus.java b/src/main/java/friend/spring/apiPayload/code/status/SuccessStatus.java new file mode 100644 index 0000000..940cfcf --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/code/status/SuccessStatus.java @@ -0,0 +1,44 @@ +package friend.spring.apiPayload.code.status; + +import friend.spring.apiPayload.code.BaseErrorCode; +import friend.spring.apiPayload.code.ErrorReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum SuccessStatus implements BaseErrorCode { + // 가장 일반적인 응답 + _OK(HttpStatus.OK, "COMMON200", "요청에 성공했습니다."), + ; + + // 멤버 관련 응답 + + // ~~~ 관련 응답 .... + + + private final HttpStatus httpStatus; + private final String code; + private final String message; + + @Override + public ErrorReasonDTO getReason() { + return ErrorReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(false) + .build(); + } + + @Override + public ErrorReasonDTO getReasonHttpStatus() { + return ErrorReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(false) + .httpStatus(httpStatus) + .build() + ; + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java new file mode 100644 index 0000000..2d50095 --- /dev/null +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -0,0 +1,4 @@ +package friend.spring.converter; + +public class UserConverter { +} diff --git a/src/main/java/friend/spring/domain/Alarm.java b/src/main/java/friend/spring/domain/Alarm.java new file mode 100644 index 0000000..7bd845c --- /dev/null +++ b/src/main/java/friend/spring/domain/Alarm.java @@ -0,0 +1,32 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import friend.spring.domain.enums.AlarmType; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Alarm extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Enumerated(EnumType.STRING) + @Column + private AlarmType type; + + @Column(nullable = false, length = 100) + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; +} diff --git a/src/main/java/friend/spring/domain/Comment.java b/src/main/java/friend/spring/domain/Comment.java new file mode 100644 index 0000000..39dd836 --- /dev/null +++ b/src/main/java/friend/spring/domain/Comment.java @@ -0,0 +1,47 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import friend.spring.domain.mapping.Comment_choice; +import friend.spring.domain.mapping.Comment_like; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Comment extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, length = 500) + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + // 부모 댓글 정의 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "parent_id") + private Comment parentComment; + + // 자식 댓글 정의 + @OneToMany(mappedBy = "parentComment") + private List subCommentList = new ArrayList<>(); + + @OneToMany(mappedBy = "comment") + private List commentChoiceList = new ArrayList<>(); + + @OneToMany(mappedBy = "comment") + private List commentLikeList = new ArrayList<>(); +} diff --git a/src/main/java/friend/spring/domain/Gauge_question.java b/src/main/java/friend/spring/domain/Gauge_question.java new file mode 100644 index 0000000..b85dcf8 --- /dev/null +++ b/src/main/java/friend/spring/domain/Gauge_question.java @@ -0,0 +1,33 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import friend.spring.domain.mapping.Comment_choice; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Gauge_question extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Integer min; + + @Column(nullable = false) + private Integer max; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + @OneToMany(mappedBy = "gaugeQuestion") + private List gaugeVoteList = new ArrayList<>(); +} diff --git a/src/main/java/friend/spring/domain/Gauge_vote.java b/src/main/java/friend/spring/domain/Gauge_vote.java new file mode 100644 index 0000000..0457130 --- /dev/null +++ b/src/main/java/friend/spring/domain/Gauge_vote.java @@ -0,0 +1,27 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Gauge_vote extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Integer gauge; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "gauge_question_id") + private Gauge_question gaugeQuestion; +} diff --git a/src/main/java/friend/spring/domain/General_question.java b/src/main/java/friend/spring/domain/General_question.java new file mode 100644 index 0000000..dd1cb6a --- /dev/null +++ b/src/main/java/friend/spring/domain/General_question.java @@ -0,0 +1,86 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class General_question extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String candidate1; + + @Column(nullable = true) + private String candidate2; + + @Column(nullable = true) + private String candidate3; + + @Column(nullable = true) + private String candidate4; + + @Column(nullable = true) + private String candidate5; + + @Column(nullable = true) + private String candidate6; + + @Column(nullable = true) + private String candidate7; + + @Column(nullable = true) + private String candidate8; + + @Column(nullable = true) + private String candidate9; + + @Column(nullable = true) + private String candidate10; + + @Column(nullable = true) + private String c1_img; + + @Column(nullable = true) + private String c2_img; + + @Column(nullable = true) + private String c3_img; + + @Column(nullable = true) + private String c4_img; + + @Column(nullable = true) + private String c5_img; + + @Column(nullable = true) + private String c6_img; + + @Column(nullable = true) + private String c7_img; + + @Column(nullable = true) + private String c8_img; + + @Column(nullable = true) + private String c9_img; + + @Column(nullable = true) + private String c10_img; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + @OneToMany(mappedBy = "generalQuestion") + private List generalVoteList = new ArrayList<>(); +} diff --git a/src/main/java/friend/spring/domain/General_vote.java b/src/main/java/friend/spring/domain/General_vote.java new file mode 100644 index 0000000..8c8e72a --- /dev/null +++ b/src/main/java/friend/spring/domain/General_vote.java @@ -0,0 +1,54 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class General_vote extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Boolean select1; + + @Column(nullable = true) + private Boolean select2; + + @Column(nullable = true) + private Boolean select3; + + @Column(nullable = true) + private Boolean select4; + + @Column(nullable = true) + private Boolean select5; + + @Column(nullable = true) + private Boolean select6; + + @Column(nullable = true) + private Boolean select7; + + @Column(nullable = true) + private Boolean select8; + + @Column(nullable = true) + private Boolean select9; + + @Column(nullable = true) + private Boolean select10; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "general_question_id") + private General_question generalQuestion; +} diff --git a/src/main/java/friend/spring/domain/Level.java b/src/main/java/friend/spring/domain/Level.java new file mode 100644 index 0000000..071f6a0 --- /dev/null +++ b/src/main/java/friend/spring/domain/Level.java @@ -0,0 +1,28 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Level extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, length = 10) + private String name; + + @Column(nullable = false) + private Integer like; + + @OneToMany(mappedBy = "level") + private List userList = new ArrayList<>(); +} diff --git a/src/main/java/friend/spring/domain/Point.java b/src/main/java/friend/spring/domain/Point.java new file mode 100644 index 0000000..98aed41 --- /dev/null +++ b/src/main/java/friend/spring/domain/Point.java @@ -0,0 +1,26 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Point extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, length = 100) + private String content; + + @Column(nullable = false) + private Integer amount; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; +} diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java new file mode 100644 index 0000000..70ea877 --- /dev/null +++ b/src/main/java/friend/spring/domain/Post.java @@ -0,0 +1,94 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import friend.spring.domain.enums.PostState; +import friend.spring.domain.enums.PostType; +import friend.spring.domain.enums.PostVoteType; +import friend.spring.domain.mapping.Comment_choice; +import friend.spring.domain.mapping.Post_like; +import friend.spring.domain.mapping.Post_scrap; +import jakarta.persistence.*; +import lombok.*; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Post extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, length = 30) + private String title; + + @Column(nullable = false, length = 1000) + private String content; + + @Enumerated(EnumType.STRING) + @Column + private PostType postType; + + @Enumerated(EnumType.STRING) + @Column + private PostVoteType voteType; + + @Column(nullable = true, length = 1000) + private String file; + + @Column(nullable = true, length = 100) + private String tag; + + @Enumerated(EnumType.STRING) + @Column + private PostState state; + + @Column(nullable = false) + private Integer view; + + @Column(nullable = true) + private Timestamp deadline; + + @Column(nullable = true) + private Integer point; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + // 부모 글 정의 + // 고민후기 원글 아이디 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "parent_id") + private Post parentPost; + + // 자식 글 정의 + @OneToMany(mappedBy = "parentPost") + private List reviewPostList = new ArrayList<>(); + + @OneToMany(mappedBy = "post") + private List alarmList = new ArrayList<>(); + + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) + private List postLikeList = new ArrayList<>(); + + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) + private List postScrapList = new ArrayList<>(); + + @OneToMany(mappedBy = "post") + private List commentList = new ArrayList<>(); + + @OneToMany(mappedBy = "post") + private List commentChoiceList = new ArrayList<>(); + + @OneToMany(mappedBy = "post") + private List generalQuestionList = new ArrayList<>(); + + @OneToMany(mappedBy = "post") + private List gaugeQuestionList = new ArrayList<>(); +} diff --git a/src/main/java/friend/spring/domain/Report.java b/src/main/java/friend/spring/domain/Report.java new file mode 100644 index 0000000..169c82c --- /dev/null +++ b/src/main/java/friend/spring/domain/Report.java @@ -0,0 +1,37 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import friend.spring.domain.enums.AlarmType; +import friend.spring.domain.enums.ReportCategory; +import friend.spring.domain.enums.ReportType; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Report extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Enumerated(EnumType.STRING) + @Column + private ReportType targetType; + + @Column(nullable = false) + private Integer targetId; + + @Column(nullable = false, length = 500) + private String content; + + @Enumerated(EnumType.STRING) + @Column + private ReportCategory category; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; +} diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java new file mode 100644 index 0000000..35fbb76 --- /dev/null +++ b/src/main/java/friend/spring/domain/User.java @@ -0,0 +1,104 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import friend.spring.domain.enums.Gender; +import friend.spring.domain.mapping.Comment_choice; +import friend.spring.domain.mapping.Comment_like; +import friend.spring.domain.mapping.Post_like; +import friend.spring.domain.mapping.Post_scrap; +import jakarta.persistence.*; +import lombok.*; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class User extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, length = 15) + private String login_id; + + @Column(nullable = false, length = 20) + private String pw; + + @Column(nullable = false, length = 50) + private String email; + + @Column(nullable = false, length = 15) + private String name; + + @Column(nullable = false, length = 15) + private String phone; + + @Enumerated(EnumType.STRING) + @Column + private Gender gender; + + @Column(nullable = false, length = 30) + private String nickname; + + @DateTimeFormat(pattern = "yyyy-MM-dd") + @Column(nullable = false) + private LocalDate birth; + + @Column(nullable = false) + private Boolean event; + + @Column(nullable = true) + private String image; + + @Column(nullable = false) + private Boolean is_deleted; + + @Column(nullable = true) + private Integer point; + + @Column(nullable = true) + private String kakao; + + @Column(nullable = false) + private Integer like; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "level_id") + private Level level; + + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) + private List pointList = new ArrayList<>(); + + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) + private List alarmList = new ArrayList<>(); + + @OneToMany(mappedBy = "user") + private List reportList = new ArrayList<>(); + + @OneToMany(mappedBy = "user") + private List postList = new ArrayList<>(); + + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) + private List postLikeList = new ArrayList<>(); + + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) + private List postScrapList = new ArrayList<>(); + + @OneToMany(mappedBy = "user") + private List commentList = new ArrayList<>(); + + @OneToMany(mappedBy = "user") + private List commentLikeList = new ArrayList<>(); + + @OneToMany(mappedBy = "user") + private List generalVoteList = new ArrayList<>(); + + @OneToMany(mappedBy = "user") + private List gaugeVoteList = new ArrayList<>(); +} diff --git a/src/main/java/friend/spring/domain/common/BaseEntity.java b/src/main/java/friend/spring/domain/common/BaseEntity.java new file mode 100644 index 0000000..e86cd38 --- /dev/null +++ b/src/main/java/friend/spring/domain/common/BaseEntity.java @@ -0,0 +1,25 @@ +package friend.spring.domain.common; + +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +@Getter +public abstract class BaseEntity { + + @CreatedDate + @Column(nullable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + @Column(nullable = false) + private LocalDateTime updatedAt; +} diff --git a/src/main/java/friend/spring/domain/enums/AlarmType.java b/src/main/java/friend/spring/domain/enums/AlarmType.java new file mode 100644 index 0000000..57e156e --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/AlarmType.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum AlarmType { + COMMENT, VOTE_FINISH +} diff --git a/src/main/java/friend/spring/domain/enums/Gender.java b/src/main/java/friend/spring/domain/enums/Gender.java new file mode 100644 index 0000000..b9d2c44 --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/Gender.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum Gender { + NONE, MALE, FEMALE +} diff --git a/src/main/java/friend/spring/domain/enums/PostState.java b/src/main/java/friend/spring/domain/enums/PostState.java new file mode 100644 index 0000000..e48bafe --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/PostState.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum PostState { + DELETED, POSTING, TEMP +} diff --git a/src/main/java/friend/spring/domain/enums/PostType.java b/src/main/java/friend/spring/domain/enums/PostType.java new file mode 100644 index 0000000..d509e75 --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/PostType.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum PostType { + NOT_VOTE, VOTE, REVIEW +} diff --git a/src/main/java/friend/spring/domain/enums/PostVoteType.java b/src/main/java/friend/spring/domain/enums/PostVoteType.java new file mode 100644 index 0000000..d1cd6a4 --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/PostVoteType.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum PostVoteType { + GENERAL, GAUGE +} diff --git a/src/main/java/friend/spring/domain/enums/ReportCategory.java b/src/main/java/friend/spring/domain/enums/ReportCategory.java new file mode 100644 index 0000000..1c79bbf --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/ReportCategory.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum ReportCategory { + SPAM, PRONO, NOT_FIT_POST, ABUSE, AD +} diff --git a/src/main/java/friend/spring/domain/enums/ReportType.java b/src/main/java/friend/spring/domain/enums/ReportType.java new file mode 100644 index 0000000..04a2e0c --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/ReportType.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum ReportType { + POST, COMMENT +} diff --git a/src/main/java/friend/spring/domain/mapping/Comment_choice.java b/src/main/java/friend/spring/domain/mapping/Comment_choice.java new file mode 100644 index 0000000..c96933c --- /dev/null +++ b/src/main/java/friend/spring/domain/mapping/Comment_choice.java @@ -0,0 +1,29 @@ +package friend.spring.domain.mapping; + +import friend.spring.domain.Comment; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Comment_choice extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private Integer point; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "comment_id") + private Comment comment; +} diff --git a/src/main/java/friend/spring/domain/mapping/Comment_like.java b/src/main/java/friend/spring/domain/mapping/Comment_like.java new file mode 100644 index 0000000..50ad346 --- /dev/null +++ b/src/main/java/friend/spring/domain/mapping/Comment_like.java @@ -0,0 +1,28 @@ +package friend.spring.domain.mapping; + +import friend.spring.domain.Comment; +import friend.spring.domain.User; +import friend.spring.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Comment_like extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private Integer point; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "comment_id") + private Comment comment; +} diff --git a/src/main/java/friend/spring/domain/mapping/Post_like.java b/src/main/java/friend/spring/domain/mapping/Post_like.java new file mode 100644 index 0000000..7368cfb --- /dev/null +++ b/src/main/java/friend/spring/domain/mapping/Post_like.java @@ -0,0 +1,26 @@ +package friend.spring.domain.mapping; + +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Post_like extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; +} diff --git a/src/main/java/friend/spring/domain/mapping/Post_scrap.java b/src/main/java/friend/spring/domain/mapping/Post_scrap.java new file mode 100644 index 0000000..724c035 --- /dev/null +++ b/src/main/java/friend/spring/domain/mapping/Post_scrap.java @@ -0,0 +1,26 @@ +package friend.spring.domain.mapping; + +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Post_scrap extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; +} diff --git a/src/main/java/friend/spring/repository/UserRepository.java b/src/main/java/friend/spring/repository/UserRepository.java new file mode 100644 index 0000000..88be65d --- /dev/null +++ b/src/main/java/friend/spring/repository/UserRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java new file mode 100644 index 0000000..6d726cf --- /dev/null +++ b/src/main/java/friend/spring/service/UserService.java @@ -0,0 +1,4 @@ +package friend.spring.service; + +public interface UserService { +} diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java new file mode 100644 index 0000000..7011cba --- /dev/null +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -0,0 +1,9 @@ +package friend.spring.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class UserServiceImpl implements UserService { +} diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java new file mode 100644 index 0000000..fac613a --- /dev/null +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -0,0 +1,12 @@ +package friend.spring.web.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/user") +public class UserRestController { + +} diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java new file mode 100644 index 0000000..089a5f4 --- /dev/null +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -0,0 +1,4 @@ +package friend.spring.web.dto; + +public class UserRequestDTO { +} diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java new file mode 100644 index 0000000..6f17e26 --- /dev/null +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -0,0 +1,4 @@ +package friend.spring.web.dto; + +public class UserResponseDTO { +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..a360a55 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,20 @@ +spring: + datasource: + url: jdbc:mysql://solutionfrienddb.cxuwucgcsxaw.ap-northeast-2.rds.amazonaws.com:3306/Solution_friendDB + username: root + password: Gomin5!! + driver-class-name: com.mysql.cj.jdbc.Driver + sql: + init: + mode: never + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL8Dialect + show_sql: true + format_sql: true + use_sql_comments: true + hbm2ddl: + auto: create + default_batch_fetch_size: 1000 + globally_quoted_identifiers: true \ No newline at end of file From 9b5ff560a88e7b824a77b879851c83d7d090deaf Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 18 Jan 2024 15:08:48 +0900 Subject: [PATCH 003/255] =?UTF-8?q?Feat:=20=EC=8A=A4=ED=94=84=EB=A7=81?= =?UTF-8?q?=EB=B6=80=ED=8A=B8/=EC=9E=90=EB=B0=94=20=EB=B2=84=EC=A0=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 6 +++--- src/main/java/friend/spring/domain/Alarm.java | 3 ++- src/main/java/friend/spring/domain/Comment.java | 2 +- src/main/java/friend/spring/domain/Gauge_question.java | 3 +-- src/main/java/friend/spring/domain/Gauge_vote.java | 3 ++- src/main/java/friend/spring/domain/General_question.java | 2 +- src/main/java/friend/spring/domain/General_vote.java | 3 ++- src/main/java/friend/spring/domain/Level.java | 2 +- src/main/java/friend/spring/domain/Point.java | 3 ++- src/main/java/friend/spring/domain/Post.java | 2 +- src/main/java/friend/spring/domain/Report.java | 4 ++-- src/main/java/friend/spring/domain/User.java | 3 +-- src/main/java/friend/spring/domain/common/BaseEntity.java | 6 +++--- .../java/friend/spring/domain/mapping/Comment_choice.java | 3 ++- .../java/friend/spring/domain/mapping/Comment_like.java | 3 ++- src/main/java/friend/spring/domain/mapping/Post_like.java | 3 ++- src/main/java/friend/spring/domain/mapping/Post_scrap.java | 3 ++- 17 files changed, 30 insertions(+), 24 deletions(-) diff --git a/build.gradle b/build.gradle index ad10e0b..c5f8a0e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,14 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.2.1' - id 'io.spring.dependency-management' version '1.1.4' + id 'org.springframework.boot' version '2.7.17' + id 'io.spring.dependency-management' version '1.0.15.RELEASE' } group = 'friend' version = '0.0.1-SNAPSHOT' java { - sourceCompatibility = '17' + sourceCompatibility = '11' } configurations { diff --git a/src/main/java/friend/spring/domain/Alarm.java b/src/main/java/friend/spring/domain/Alarm.java index 7bd845c..3df230b 100644 --- a/src/main/java/friend/spring/domain/Alarm.java +++ b/src/main/java/friend/spring/domain/Alarm.java @@ -2,9 +2,10 @@ import friend.spring.domain.common.BaseEntity; import friend.spring.domain.enums.AlarmType; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; + @Entity @Getter @Builder diff --git a/src/main/java/friend/spring/domain/Comment.java b/src/main/java/friend/spring/domain/Comment.java index 39dd836..ccdc776 100644 --- a/src/main/java/friend/spring/domain/Comment.java +++ b/src/main/java/friend/spring/domain/Comment.java @@ -3,9 +3,9 @@ import friend.spring.domain.common.BaseEntity; import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/friend/spring/domain/Gauge_question.java b/src/main/java/friend/spring/domain/Gauge_question.java index b85dcf8..472496a 100644 --- a/src/main/java/friend/spring/domain/Gauge_question.java +++ b/src/main/java/friend/spring/domain/Gauge_question.java @@ -1,10 +1,9 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; -import friend.spring.domain.mapping.Comment_choice; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/friend/spring/domain/Gauge_vote.java b/src/main/java/friend/spring/domain/Gauge_vote.java index 0457130..3181006 100644 --- a/src/main/java/friend/spring/domain/Gauge_vote.java +++ b/src/main/java/friend/spring/domain/Gauge_vote.java @@ -1,9 +1,10 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; + @Entity @Getter @Builder diff --git a/src/main/java/friend/spring/domain/General_question.java b/src/main/java/friend/spring/domain/General_question.java index dd1cb6a..92cdec9 100644 --- a/src/main/java/friend/spring/domain/General_question.java +++ b/src/main/java/friend/spring/domain/General_question.java @@ -1,9 +1,9 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/friend/spring/domain/General_vote.java b/src/main/java/friend/spring/domain/General_vote.java index 8c8e72a..e14a90c 100644 --- a/src/main/java/friend/spring/domain/General_vote.java +++ b/src/main/java/friend/spring/domain/General_vote.java @@ -1,9 +1,10 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; + @Entity @Getter @Builder diff --git a/src/main/java/friend/spring/domain/Level.java b/src/main/java/friend/spring/domain/Level.java index 071f6a0..2279ee5 100644 --- a/src/main/java/friend/spring/domain/Level.java +++ b/src/main/java/friend/spring/domain/Level.java @@ -1,9 +1,9 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/friend/spring/domain/Point.java b/src/main/java/friend/spring/domain/Point.java index 98aed41..88b871a 100644 --- a/src/main/java/friend/spring/domain/Point.java +++ b/src/main/java/friend/spring/domain/Point.java @@ -1,9 +1,10 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; + @Entity @Getter @Builder diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 70ea877..51ff324 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -7,9 +7,9 @@ import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/friend/spring/domain/Report.java b/src/main/java/friend/spring/domain/Report.java index 169c82c..cf87d47 100644 --- a/src/main/java/friend/spring/domain/Report.java +++ b/src/main/java/friend/spring/domain/Report.java @@ -1,12 +1,12 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; -import friend.spring.domain.enums.AlarmType; import friend.spring.domain.enums.ReportCategory; import friend.spring.domain.enums.ReportType; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; + @Entity @Getter @Builder diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 35fbb76..b455f95 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -2,14 +2,13 @@ import friend.spring.domain.common.BaseEntity; import friend.spring.domain.enums.Gender; -import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; -import jakarta.persistence.*; import lombok.*; import org.springframework.format.annotation.DateTimeFormat; +import javax.persistence.*; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/friend/spring/domain/common/BaseEntity.java b/src/main/java/friend/spring/domain/common/BaseEntity.java index e86cd38..80f5ebc 100644 --- a/src/main/java/friend/spring/domain/common/BaseEntity.java +++ b/src/main/java/friend/spring/domain/common/BaseEntity.java @@ -1,13 +1,13 @@ package friend.spring.domain.common; -import jakarta.persistence.Column; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.MappedSuperclass; import lombok.Getter; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; import java.time.LocalDateTime; @MappedSuperclass diff --git a/src/main/java/friend/spring/domain/mapping/Comment_choice.java b/src/main/java/friend/spring/domain/mapping/Comment_choice.java index c96933c..a676598 100644 --- a/src/main/java/friend/spring/domain/mapping/Comment_choice.java +++ b/src/main/java/friend/spring/domain/mapping/Comment_choice.java @@ -4,9 +4,10 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.common.BaseEntity; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; + @Entity @Getter @Builder diff --git a/src/main/java/friend/spring/domain/mapping/Comment_like.java b/src/main/java/friend/spring/domain/mapping/Comment_like.java index 50ad346..1a6ca80 100644 --- a/src/main/java/friend/spring/domain/mapping/Comment_like.java +++ b/src/main/java/friend/spring/domain/mapping/Comment_like.java @@ -3,9 +3,10 @@ import friend.spring.domain.Comment; import friend.spring.domain.User; import friend.spring.domain.common.BaseEntity; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; + @Entity @Getter @Builder diff --git a/src/main/java/friend/spring/domain/mapping/Post_like.java b/src/main/java/friend/spring/domain/mapping/Post_like.java index 7368cfb..4fcdf7f 100644 --- a/src/main/java/friend/spring/domain/mapping/Post_like.java +++ b/src/main/java/friend/spring/domain/mapping/Post_like.java @@ -3,9 +3,10 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.common.BaseEntity; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; + @Entity @Getter @Builder diff --git a/src/main/java/friend/spring/domain/mapping/Post_scrap.java b/src/main/java/friend/spring/domain/mapping/Post_scrap.java index 724c035..6103a08 100644 --- a/src/main/java/friend/spring/domain/mapping/Post_scrap.java +++ b/src/main/java/friend/spring/domain/mapping/Post_scrap.java @@ -3,9 +3,10 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.common.BaseEntity; -import jakarta.persistence.*; import lombok.*; +import javax.persistence.*; + @Entity @Getter @Builder From db064585ef9848fab804e0ff4e5c43f5e72c5bbb Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 18 Jan 2024 15:18:49 +0900 Subject: [PATCH 004/255] =?UTF-8?q?Feat:=20gitignore=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ build.gradle | 1 + 2 files changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index c2065bc..89cc254 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ build/ !**/src/main/**/build/ !**/src/test/**/build/ +application.yml + ### STS ### .apt_generated .classpath diff --git a/build.gradle b/build.gradle index c5f8a0e..ea26407 100644 --- a/build.gradle +++ b/build.gradle @@ -28,6 +28,7 @@ dependencies { runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'mysql:mysql-connector-java:8.0.35' } tasks.named('test') { From 4253a37da96df6267bd8ca41efd428296f36a2c9 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 18 Jan 2024 15:22:18 +0900 Subject: [PATCH 005/255] =?UTF-8?q?Feat:=20application.yml=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 src/main/resources/application.yml diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml deleted file mode 100644 index a360a55..0000000 --- a/src/main/resources/application.yml +++ /dev/null @@ -1,20 +0,0 @@ -spring: - datasource: - url: jdbc:mysql://solutionfrienddb.cxuwucgcsxaw.ap-northeast-2.rds.amazonaws.com:3306/Solution_friendDB - username: root - password: Gomin5!! - driver-class-name: com.mysql.cj.jdbc.Driver - sql: - init: - mode: never - jpa: - properties: - hibernate: - dialect: org.hibernate.dialect.MySQL8Dialect - show_sql: true - format_sql: true - use_sql_comments: true - hbm2ddl: - auto: create - default_batch_fetch_size: 1000 - globally_quoted_identifiers: true \ No newline at end of file From df78d5a5fc52c693e94c76857b3ca7fafd3b73bb Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 18 Jan 2024 15:49:48 +0900 Subject: [PATCH 006/255] =?UTF-8?q?Docs:=20=EB=A6=AC=EB=93=9C=EB=AF=B8=20?= =?UTF-8?q?=EC=BB=A4=EB=B0=8B=20=EA=B7=9C=EC=B9=99=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index caa8310..2caf417 100644 --- a/README.md +++ b/README.md @@ -1 +1,20 @@ -# BE \ No newline at end of file +# BE + +### 커밋 규칙 + +| 커밋 유형 | 의미 | +|-------|-----------| +| Feat | 새로운 기능 추가 | +| Fix | 버그 수정 | +| Docs | 문서 수정 | +| Docs | 문서 수정 | +| Style | 코드 formatting, 세미콜론 누락, 코드 자체의 변경이 없는 경우 | +| Refactor | 코드 리팩토링 | +| Test | 테스트 코드, 리팩토링 테스트 코드 추가 | +| Chore | 패키지 매니저 수정, 그 외 기타 수정 ex) .gitignore | +| Design | CSS 등 사용자 UI 디자인 변경 | +| Comment | 필요한 주석 추가 및 변경 | +| Rename | 파일 또는 폴더 명을 수정하거나 옮기는 작업만인 경우 | +| Remove | 파일을 삭제하는 작업만 수행한 경우 | +| !BREAKING CHANGE | 커다란 API 변경의 경우 | +| !HOTFIX | 급하게 치명적인 버그를 고쳐야 하는 경우 | \ No newline at end of file From e8695250067e967368e7d64e549fb5870e36ef21 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 18 Jan 2024 16:29:16 +0900 Subject: [PATCH 007/255] =?UTF-8?q?Docs:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2caf417..088efae 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# BE +# BE 고민친구 ### 커밋 규칙 From 63b4590b9a95ab0fcfa016ed36e7f07b04327cf3 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Thu, 18 Jan 2024 17:20:21 +0900 Subject: [PATCH 008/255] =?UTF-8?q?dependencies=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index ea26407..ef3fc09 100644 --- a/build.gradle +++ b/build.gradle @@ -29,6 +29,12 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'mysql:mysql-connector-java:8.0.35' + + //jwt + testImplementation 'org.springframework.security:spring-security-test' + implementation 'io.jsonwebtoken:jjwt-api:0.12.3' + implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' + implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' } tasks.named('test') { From ad8ed8fc65f480c8c1640857b44635354fcc27b1 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Thu, 18 Jan 2024 17:30:28 +0900 Subject: [PATCH 009/255] =?UTF-8?q?#3=20feat=20:=20Swagger=20=EC=84=B8?= =?UTF-8?q?=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 ++ .../friend/spring/config/SwaggerConfig.java | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/main/java/friend/spring/config/SwaggerConfig.java diff --git a/build.gradle b/build.gradle index ea26407..9b205ed 100644 --- a/build.gradle +++ b/build.gradle @@ -29,6 +29,9 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'mysql:mysql-connector-java:8.0.35' + implementation 'org.springdoc:springdoc-openapi-ui:1.6.15' + implementation 'io.springfox:springfox-swagger2:2.9.2' + implementation 'io.springfox:springfox-swagger-ui:2.9.2' } tasks.named('test') { diff --git a/src/main/java/friend/spring/config/SwaggerConfig.java b/src/main/java/friend/spring/config/SwaggerConfig.java new file mode 100644 index 0000000..0f4e9cc --- /dev/null +++ b/src/main/java/friend/spring/config/SwaggerConfig.java @@ -0,0 +1,37 @@ +package friend.spring.config; + +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; +import org.springframework.context.annotation.Bean; + +public class SwaggerConfig { + @Bean + public OpenAPI UMCstudyAPI() { + Info info = new Info() + .title("고민친구 Server API") + .description("고민친구 API 명세서") + .version("1.0.0"); + + String jwtSchemeName = "JWT TOKEN"; + // API 요청헤더에 인증정보 포함 + SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtSchemeName); + // SecuritySchemes 등록 + Components components = new Components() + .addSecuritySchemes(jwtSchemeName, new SecurityScheme() + .name(jwtSchemeName) + .type(SecurityScheme.Type.HTTP) // HTTP 방식 + .scheme("bearer") + .bearerFormat("JWT")); + + return new OpenAPI() + .addServersItem(new Server().url("/")) + .info(info) + .addSecurityItem(securityRequirement) + .components(components); + } +} + From cb1e82fdb92bc7496f5f4557d94198dd9c81b24f Mon Sep 17 00:00:00 2001 From: hjh Date: Thu, 18 Jan 2024 17:48:15 +0900 Subject: [PATCH 010/255] test --- src/main/java/friend/spring/web/dto/UserRequestDTO.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 089a5f4..4405f00 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -1,4 +1,5 @@ package friend.spring.web.dto; public class UserRequestDTO { + //hello } From 38fc0f0bd33c4977ae9e5a0119710fea27663f82 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 20 Jan 2024 09:06:30 +0900 Subject: [PATCH 011/255] =?UTF-8?q?#5=20Chore:=20CI=20dev=5Fdeploy.yml=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev_deploy.yml | 61 ++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .github/workflows/dev_deploy.yml diff --git a/.github/workflows/dev_deploy.yml b/.github/workflows/dev_deploy.yml new file mode 100644 index 0000000..f754459 --- /dev/null +++ b/.github/workflows/dev_deploy.yml @@ -0,0 +1,61 @@ +name: Solution-friend Dev CI/CD + +on: + pull_request: + types: [closed] + workflow_dispatch: # (2).수동 실행도 가능하도록 + +jobs: + build: + runs-on: ubuntu-latest # (3).OS환경 + if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'develop' + + steps: + - name: Checkout + uses: actions/checkout@v2 # (4).코드 check out + + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: 11 # (5).자바 설치 + distribution: 'adopt' + + - name: Grant execute permission for gradlew + run: chmod +x ./gradlew + shell: bash # (6).권한 부여 + + - name: Build with Gradle + run: ./gradlew clean build -x test + shell: bash # (7).build시작 + + - name: Get current time + uses: 1466587594/get-current-time@v2 + id: current-time + with: + format: YYYY-MM-DDTHH-mm-ss + utcOffset: "+09:00" # (8).build시점의 시간확보 + + - name: Show Current Time + run: echo "CurrentTime=$" + shell: bash # (9).확보한 시간 보여주기 + + - name: Generate deployment package + run: | + mkdir -p deploy + cp build/libs/*.jar deploy/application.jar + cp Procfile deploy/Procfile + cp -r .ebextensions-dev deploy/.ebextensions + cp -r .platform deploy/.platform + cd deploy && zip -r deploy.zip . + + - name: Beanstalk Deploy + uses: einaregilsson/beanstalk-deploy@v20 + with: + aws_access_key: ${{ secrets.AWS_ACTION_ACCESS_KEY_ID }} + aws_secret_key: ${{ secrets.AWS_ACTION_SECRET_ACCESS_KEY }} + application_name: breifing-dev + environment_name: Breifing-dev-env + version_label: github-action-${{ steps.current-time.outputs.formattedTime }} + region: ap-northeast-1 + deployment_package: deploy/deploy.zip + wait_for_deployment: false From 7161c46bbf27d4255de5119396664012c4a447ba Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 20 Jan 2024 09:16:56 +0900 Subject: [PATCH 012/255] =?UTF-8?q?#5=20Chore:=20CI=20dev=5Fdeploy.yml=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev_deploy.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/dev_deploy.yml b/.github/workflows/dev_deploy.yml index f754459..bed0e48 100644 --- a/.github/workflows/dev_deploy.yml +++ b/.github/workflows/dev_deploy.yml @@ -48,14 +48,14 @@ jobs: cp -r .platform deploy/.platform cd deploy && zip -r deploy.zip . - - name: Beanstalk Deploy - uses: einaregilsson/beanstalk-deploy@v20 - with: - aws_access_key: ${{ secrets.AWS_ACTION_ACCESS_KEY_ID }} - aws_secret_key: ${{ secrets.AWS_ACTION_SECRET_ACCESS_KEY }} - application_name: breifing-dev - environment_name: Breifing-dev-env - version_label: github-action-${{ steps.current-time.outputs.formattedTime }} - region: ap-northeast-1 - deployment_package: deploy/deploy.zip - wait_for_deployment: false + - name: Beanstalk Deploy + uses: einaregilsson/beanstalk-deploy@v20 + with: + aws_access_key: ${{ secrets.AWS_ACTION_ACCESS_KEY_ID }} + aws_secret_key: ${{ secrets.AWS_ACTION_SECRET_ACCESS_KEY }} + application_name: breifing-dev + environment_name: Breifing-dev-env + version_label: github-action-${{ steps.current-time.outputs.formattedTime }} + region: ap-northeast-1 + deployment_package: deploy/deploy.zip + wait_for_deployment: false From 9f152ee05224db50a0ec855e808eb233089b686e Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 21 Jan 2024 05:18:28 +0900 Subject: [PATCH 013/255] =?UTF-8?q?#5=20Feat:=20CI/CD=20=ED=8C=8C=EC=9D=B4?= =?UTF-8?q?=ED=94=84=EB=9D=BC=EC=9D=B8=20=EA=B5=AC=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ebextensions-dev/00-makefiles.config | 12 ++++ .ebextensions-dev/01-set-timezone.config | 3 + .platform/nginx.conf | 63 +++++++++++++++++++ .../nginx/conf.d/client_max_body_size.conf | 1 + Procfile | 1 + build.gradle | 4 ++ 6 files changed, 84 insertions(+) create mode 100644 .ebextensions-dev/00-makefiles.config create mode 100644 .ebextensions-dev/01-set-timezone.config create mode 100644 .platform/nginx.conf create mode 100644 .platform/nginx/conf.d/client_max_body_size.conf create mode 100644 Procfile diff --git a/.ebextensions-dev/00-makefiles.config b/.ebextensions-dev/00-makefiles.config new file mode 100644 index 0000000..8030404 --- /dev/null +++ b/.ebextensions-dev/00-makefiles.config @@ -0,0 +1,12 @@ +files: + "/sbin/appstart": + mode: "000755" + owner: webapp + group: webapp + content: | + #!/usr/bin/env bash + JAR_PATH=/var/app/current/application.jar + + # run app + killalljava + java -Dfile.encoding=UTF-8 -jar $JAR_PATH \ No newline at end of file diff --git a/.ebextensions-dev/01-set-timezone.config b/.ebextensions-dev/01-set-timezone.config new file mode 100644 index 0000000..869275c --- /dev/null +++ b/.ebextensions-dev/01-set-timezone.config @@ -0,0 +1,3 @@ +commands: + set_time_zone: + command: ln -f -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime \ No newline at end of file diff --git a/.platform/nginx.conf b/.platform/nginx.conf new file mode 100644 index 0000000..612092e --- /dev/null +++ b/.platform/nginx.conf @@ -0,0 +1,63 @@ +user nginx; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; +worker_processes auto; +worker_rlimit_nofile 33282; + +events { + use epoll; + worker_connections 1024; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + include conf.d/*.conf; + + map $http_upgrade $connection_upgrade { + default "upgrade"; + } + + upstream springboot { + server 127.0.0.1:8080; + keepalive 1024; + } + + server { + listen 80 default_server; + listen [::]:80 default_server; + + location / { + proxy_pass http://springboot; + # CORS 관련 헤더 추가 + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + access_log /var/log/nginx/access.log main; + + client_header_timeout 60; + client_body_timeout 60; + keepalive_timeout 60; + gzip off; + gzip_comp_level 4; + + # Include the Elastic Beanstalk generated locations + include conf.d/elasticbeanstalk/healthd.conf; + } +} \ No newline at end of file diff --git a/.platform/nginx/conf.d/client_max_body_size.conf b/.platform/nginx/conf.d/client_max_body_size.conf new file mode 100644 index 0000000..aaf16cc --- /dev/null +++ b/.platform/nginx/conf.d/client_max_body_size.conf @@ -0,0 +1 @@ +# client_max_body_size 200M; \ No newline at end of file diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..58dab8d --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: appstart \ No newline at end of file diff --git a/build.gradle b/build.gradle index dce6bbf..9234fa8 100644 --- a/build.gradle +++ b/build.gradle @@ -45,3 +45,7 @@ dependencies { tasks.named('test') { useJUnitPlatform() } + +jar { + enabled = false +} From 4cad616171512575e7c1034dbd07bbe2ca4a7768 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 21 Jan 2024 05:18:47 +0900 Subject: [PATCH 014/255] =?UTF-8?q?#5=20Feat:=20CI/CD=20=ED=8C=8C=EC=9D=B4?= =?UTF-8?q?=ED=94=84=EB=9D=BC=EC=9D=B8=20=EA=B5=AC=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev_deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev_deploy.yml b/.github/workflows/dev_deploy.yml index bed0e48..c7f3105 100644 --- a/.github/workflows/dev_deploy.yml +++ b/.github/workflows/dev_deploy.yml @@ -53,8 +53,8 @@ jobs: with: aws_access_key: ${{ secrets.AWS_ACTION_ACCESS_KEY_ID }} aws_secret_key: ${{ secrets.AWS_ACTION_SECRET_ACCESS_KEY }} - application_name: breifing-dev - environment_name: Breifing-dev-env + application_name: solution-friend-dev + environment_name: Solution-friend-dev-env version_label: github-action-${{ steps.current-time.outputs.formattedTime }} region: ap-northeast-1 deployment_package: deploy/deploy.zip From 6310820efd66b62894885414a6bd9fd5cdb2d339 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 21 Jan 2024 05:26:17 +0900 Subject: [PATCH 015/255] =?UTF-8?q?#5=20Chore:=20health=20check=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/web/controller/RootController.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/java/friend/spring/web/controller/RootController.java diff --git a/src/main/java/friend/spring/web/controller/RootController.java b/src/main/java/friend/spring/web/controller/RootController.java new file mode 100644 index 0000000..f2addc0 --- /dev/null +++ b/src/main/java/friend/spring/web/controller/RootController.java @@ -0,0 +1,12 @@ +package friend.spring.web.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class RootController { + @GetMapping("/health") + public String healthCheck() { + return "I'm healthy!"; + } +} From a4c4f38f8a8b06bbef42004c1369f91876b3e2e2 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 21 Jan 2024 08:01:05 +0900 Subject: [PATCH 016/255] =?UTF-8?q?#5=20Chore:=20application.yml=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20gitignore=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 -- src/main/resources/application.yml | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/application.yml diff --git a/.gitignore b/.gitignore index 89cc254..c2065bc 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,6 @@ build/ !**/src/main/**/build/ !**/src/test/**/build/ -application.yml - ### STS ### .apt_generated .classpath diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..0c514cb --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,20 @@ +spring: + datasource: + url: ${aws.db.url} + username: ${aws.db.username} + password: ${aws.db.password} + driver-class-name: com.mysql.cj.jdbc.Driver + sql: + init: + mode: never + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL8Dialect + show_sql: true + format_sql: true + use_sql_comments: true + hbm2ddl: + auto: update + default_batch_fetch_size: 1000 + globally_quoted_identifiers: true \ No newline at end of file From 63651142ff8a9d6f099e79d259ce60d2a24f51b2 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 21 Jan 2024 08:22:19 +0900 Subject: [PATCH 017/255] =?UTF-8?q?#5=20Chore:=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 088efae..d7b9f17 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ ### 커밋 규칙 +#{이슈번호} {type}: [작업한 내용] + +ex) #200 Feat: 사용자 뮤트 기능 추가 + | 커밋 유형 | 의미 | |-------|-----------| | Feat | 새로운 기능 추가 | From b2ee3bd892ee1ec7860eb4bc639d5fb6a21f6020 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 21 Jan 2024 09:03:53 +0900 Subject: [PATCH 018/255] =?UTF-8?q?#8=20Chore:=20CompileJava=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95=20-=20build.gradle,=20Builder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 - src/main/java/friend/spring/domain/Comment.java | 3 +++ src/main/java/friend/spring/domain/Gauge_question.java | 1 + .../java/friend/spring/domain/General_question.java | 1 + src/main/java/friend/spring/domain/Level.java | 1 + src/main/java/friend/spring/domain/Post.java | 8 ++++++++ src/main/java/friend/spring/domain/User.java | 10 ++++++++++ 7 files changed, 24 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9234fa8..310998a 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,6 @@ dependencies { runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' - implementation 'mysql:mysql-connector-java:8.0.35' //jwt testImplementation 'org.springframework.security:spring-security-test' diff --git a/src/main/java/friend/spring/domain/Comment.java b/src/main/java/friend/spring/domain/Comment.java index ccdc776..1085df8 100644 --- a/src/main/java/friend/spring/domain/Comment.java +++ b/src/main/java/friend/spring/domain/Comment.java @@ -36,12 +36,15 @@ public class Comment extends BaseEntity { private Comment parentComment; // 자식 댓글 정의 + @Builder.Default @OneToMany(mappedBy = "parentComment") private List subCommentList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "comment") private List commentChoiceList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "comment") private List commentLikeList = new ArrayList<>(); } diff --git a/src/main/java/friend/spring/domain/Gauge_question.java b/src/main/java/friend/spring/domain/Gauge_question.java index 472496a..3725db7 100644 --- a/src/main/java/friend/spring/domain/Gauge_question.java +++ b/src/main/java/friend/spring/domain/Gauge_question.java @@ -27,6 +27,7 @@ public class Gauge_question extends BaseEntity { @JoinColumn(name = "post_id") private Post post; + @Builder.Default @OneToMany(mappedBy = "gaugeQuestion") private List gaugeVoteList = new ArrayList<>(); } diff --git a/src/main/java/friend/spring/domain/General_question.java b/src/main/java/friend/spring/domain/General_question.java index 92cdec9..7544896 100644 --- a/src/main/java/friend/spring/domain/General_question.java +++ b/src/main/java/friend/spring/domain/General_question.java @@ -81,6 +81,7 @@ public class General_question extends BaseEntity { @JoinColumn(name = "post_id") private Post post; + @Builder.Default @OneToMany(mappedBy = "generalQuestion") private List generalVoteList = new ArrayList<>(); } diff --git a/src/main/java/friend/spring/domain/Level.java b/src/main/java/friend/spring/domain/Level.java index 2279ee5..064f27d 100644 --- a/src/main/java/friend/spring/domain/Level.java +++ b/src/main/java/friend/spring/domain/Level.java @@ -23,6 +23,7 @@ public class Level extends BaseEntity { @Column(nullable = false) private Integer like; + @Builder.Default @OneToMany(mappedBy = "level") private List userList = new ArrayList<>(); } diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 51ff324..9e110a3 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -68,27 +68,35 @@ public class Post extends BaseEntity { private Post parentPost; // 자식 글 정의 + @Builder.Default @OneToMany(mappedBy = "parentPost") private List reviewPostList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post") private List alarmList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private List postLikeList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private List postScrapList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post") private List commentList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post") private List commentChoiceList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post") private List generalQuestionList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post") private List gaugeQuestionList = new ArrayList<>(); } diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index b455f95..193e5bd 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -71,33 +71,43 @@ public class User extends BaseEntity { @JoinColumn(name = "level_id") private Level level; + @Builder.Default @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) private List pointList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) private List alarmList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "user") private List reportList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "user") private List postList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) private List postLikeList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) private List postScrapList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "user") private List commentList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "user") private List commentLikeList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "user") private List generalVoteList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "user") private List gaugeVoteList = new ArrayList<>(); } From 3edeba7e1a16288fb0f97001eb1ae9a580cf534d Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 21 Jan 2024 09:32:22 +0900 Subject: [PATCH 019/255] =?UTF-8?q?#8=20Chore:=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d7b9f17..5c740e4 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ ex) #200 Feat: 사용자 뮤트 기능 추가 + | 커밋 유형 | 의미 | |-------|-----------| | Feat | 새로운 기능 추가 | From 8da5820bec33bad5302a8afa1ccaf115a7988bcf Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 21 Jan 2024 22:40:22 +0900 Subject: [PATCH 020/255] =?UTF-8?q?#8=20Chore:=20=EB=A6=AC=EC=A0=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev_deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev_deploy.yml b/.github/workflows/dev_deploy.yml index c7f3105..21bf8e1 100644 --- a/.github/workflows/dev_deploy.yml +++ b/.github/workflows/dev_deploy.yml @@ -56,6 +56,6 @@ jobs: application_name: solution-friend-dev environment_name: Solution-friend-dev-env version_label: github-action-${{ steps.current-time.outputs.formattedTime }} - region: ap-northeast-1 + region: ap-northeast-2 deployment_package: deploy/deploy.zip wait_for_deployment: false From f5bdc04feec06b0dc9a4b9cf1992e6d8d00b38e1 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 22 Jan 2024 10:26:59 +0900 Subject: [PATCH 021/255] =?UTF-8?q?#8=20Feat:=20S3=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../friend/spring/aws/s3/AmazonS3Manager.java | 50 +++++++++++++++ .../friend/spring/config/AmazonConfig.java | 62 +++++++++++++++++++ src/main/java/friend/spring/domain/Uuid.java | 20 ++++++ .../spring/repository/UserRepository.java | 2 + .../spring/repository/UuidRepository.java | 9 +++ .../java/friend/spring/service/S3Service.java | 30 +++++++++ .../spring/web/controller/RootController.java | 2 + .../spring/web/controller/S3Controller.java | 26 ++++++++ src/main/resources/application.yml | 23 ++++++- 10 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 src/main/java/friend/spring/aws/s3/AmazonS3Manager.java create mode 100644 src/main/java/friend/spring/config/AmazonConfig.java create mode 100644 src/main/java/friend/spring/domain/Uuid.java create mode 100644 src/main/java/friend/spring/repository/UuidRepository.java create mode 100644 src/main/java/friend/spring/service/S3Service.java create mode 100644 src/main/java/friend/spring/web/controller/S3Controller.java diff --git a/build.gradle b/build.gradle index 310998a..b2b74ff 100644 --- a/build.gradle +++ b/build.gradle @@ -39,6 +39,8 @@ dependencies { implementation 'io.springfox:springfox-swagger2:2.9.2' implementation 'io.springfox:springfox-swagger-ui:2.9.2' + // S3 + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' } tasks.named('test') { diff --git a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java new file mode 100644 index 0000000..eb9a0c0 --- /dev/null +++ b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java @@ -0,0 +1,50 @@ +package friend.spring.aws.s3; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import friend.spring.config.AmazonConfig; +import friend.spring.domain.Uuid; +import friend.spring.repository.UuidRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +@Slf4j +@Component +@RequiredArgsConstructor +public class AmazonS3Manager{ + + private final AmazonS3 amazonS3; + + private final AmazonConfig amazonConfig; + + private final UuidRepository uuidRepository; + + public String uploadFile(String keyName, MultipartFile file){ + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentLength(file.getSize()); + try { + amazonS3.putObject(new PutObjectRequest(amazonConfig.getBucket(), keyName, file.getInputStream(), metadata)); + }catch (IOException e){ + log.error("error at AmazonS3Manager uploadFile : {}", (Object) e.getStackTrace()); + } + + return amazonS3.getUrl(amazonConfig.getBucket(), keyName).toString(); + } + + public String generateUserKeyName(Uuid uuid) { + return amazonConfig.getUserPath() + '/' + uuid.getUuid(); + } + + public String generatePostKeyName(Uuid uuid) { + return amazonConfig.getPostPath() + '/' + uuid.getUuid(); + } + + public String generateReportKeyName(Uuid uuid) { + return amazonConfig.getReportPath() + '/' + uuid.getUuid(); + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/config/AmazonConfig.java b/src/main/java/friend/spring/config/AmazonConfig.java new file mode 100644 index 0000000..a0597eb --- /dev/null +++ b/src/main/java/friend/spring/config/AmazonConfig.java @@ -0,0 +1,62 @@ +package friend.spring.config; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; + +@Configuration +@Getter +public class AmazonConfig { + + + private AWSCredentials awsCredentials; + + @Value("${cloud.aws.credentials.accessKey}") + private String accessKey; + + @Value("${cloud.aws.credentials.secretKey}") + private String secretKey; + + @Value("${cloud.aws.region.static}") + private String region; + + @Value("${cloud.aws.s3.bucket}") + private String bucket; + + @Value("${cloud.aws.s3.path.user}") + private String userPath; + + @Value("${cloud.aws.s3.path.post}") + private String postPath; + + @Value("${cloud.aws.s3.path.report}") + private String reportPath; + + @PostConstruct + public void init() { + this.awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + } + + @Bean + public AmazonS3 amazonS3() { + AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + return AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .build(); + } + + @Bean + public AWSCredentialsProvider awsCredentialsProvider() { + return new AWSStaticCredentialsProvider(awsCredentials); + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/domain/Uuid.java b/src/main/java/friend/spring/domain/Uuid.java new file mode 100644 index 0000000..d4c13ee --- /dev/null +++ b/src/main/java/friend/spring/domain/Uuid.java @@ -0,0 +1,20 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import lombok.*; + +import javax.persistence.*; + +@Entity +@Builder +@Getter +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Uuid extends BaseEntity { // S3 업로드 시 사진 각각을 식별해주는 UUID + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(unique = true) + private String uuid; +} diff --git a/src/main/java/friend/spring/repository/UserRepository.java b/src/main/java/friend/spring/repository/UserRepository.java index 88be65d..d002975 100644 --- a/src/main/java/friend/spring/repository/UserRepository.java +++ b/src/main/java/friend/spring/repository/UserRepository.java @@ -2,6 +2,8 @@ import friend.spring.domain.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface UserRepository extends JpaRepository { } diff --git a/src/main/java/friend/spring/repository/UuidRepository.java b/src/main/java/friend/spring/repository/UuidRepository.java new file mode 100644 index 0000000..fcbbd4c --- /dev/null +++ b/src/main/java/friend/spring/repository/UuidRepository.java @@ -0,0 +1,9 @@ +package friend.spring.repository; + +import friend.spring.domain.Uuid; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UuidRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/service/S3Service.java b/src/main/java/friend/spring/service/S3Service.java new file mode 100644 index 0000000..ced2c78 --- /dev/null +++ b/src/main/java/friend/spring/service/S3Service.java @@ -0,0 +1,30 @@ +package friend.spring.service; + +import friend.spring.aws.s3.AmazonS3Manager; +import friend.spring.domain.Uuid; +import friend.spring.repository.UuidRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.UUID; + +@Service +@Transactional +@RequiredArgsConstructor +public class S3Service { + private final UuidRepository uuidRepository; + private final AmazonS3Manager s3Manager; + + // 유저 프로필 사진 올리기인 경우 + public String uploadUserImage(MultipartFile file) { + String uuid = UUID.randomUUID().toString(); + Uuid savedUuid = uuidRepository.save(Uuid.builder() + .uuid(uuid).build()); + + String pictureUrl = s3Manager.uploadFile(s3Manager.generateUserKeyName(savedUuid), file); + return pictureUrl; + } +} diff --git a/src/main/java/friend/spring/web/controller/RootController.java b/src/main/java/friend/spring/web/controller/RootController.java index f2addc0..7293285 100644 --- a/src/main/java/friend/spring/web/controller/RootController.java +++ b/src/main/java/friend/spring/web/controller/RootController.java @@ -9,4 +9,6 @@ public class RootController { public String healthCheck() { return "I'm healthy!"; } + + } diff --git a/src/main/java/friend/spring/web/controller/S3Controller.java b/src/main/java/friend/spring/web/controller/S3Controller.java new file mode 100644 index 0000000..178fe55 --- /dev/null +++ b/src/main/java/friend/spring/web/controller/S3Controller.java @@ -0,0 +1,26 @@ +package friend.spring.web.controller; + +import friend.spring.apiPayload.ApiResponse; +import friend.spring.aws.s3.AmazonS3Manager; +import friend.spring.service.S3Service; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@RequiredArgsConstructor +@RestController +@RequestMapping("/uploadImage") +public class S3Controller { + private final S3Service s3Service; + + // 유저 이미지 올리기 + @PostMapping(value = "", consumes = "multipart/form-data") + public ApiResponse uploadUserImage(@RequestPart(value = "file", required = false) MultipartFile file) { + String url = s3Service.uploadUserImage(file); + return ApiResponse.onSuccess(url); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 0c514cb..5334bb7 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -17,4 +17,25 @@ spring: hbm2ddl: auto: update default_batch_fetch_size: 1000 - globally_quoted_identifiers: true \ No newline at end of file + globally_quoted_identifiers: true + cloud: + aws: + s3: + bucket: solution-friend-bucket + path: + user: users + post: posts + report: reports + region: + static: ap-northeast-2 + stack: + auto: false + credentials: + accessKey: ${AWS_ACCESS_KEY_ID} + secretKey: ${AWS_SECRET_ACCESS_KEY} + logging: + level: + com: + amazonaws: + util: + EC2MetadataUtils: error \ No newline at end of file From aa3ea688306a5b2d4a1fdfca942af537261823d9 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 23 Jan 2024 05:34:54 +0900 Subject: [PATCH 022/255] =?UTF-8?q?#8=20Chore:=20application.yml=20cloud?= =?UTF-8?q?=20=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/service/S3Service.java | 1 - .../spring/web/controller/S3Controller.java | 11 ++--- src/main/resources/application.yml | 42 +++++++++---------- 3 files changed, 24 insertions(+), 30 deletions(-) diff --git a/src/main/java/friend/spring/service/S3Service.java b/src/main/java/friend/spring/service/S3Service.java index ced2c78..2c34a8f 100644 --- a/src/main/java/friend/spring/service/S3Service.java +++ b/src/main/java/friend/spring/service/S3Service.java @@ -8,7 +8,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; -import java.io.IOException; import java.util.UUID; @Service diff --git a/src/main/java/friend/spring/web/controller/S3Controller.java b/src/main/java/friend/spring/web/controller/S3Controller.java index 178fe55..8052453 100644 --- a/src/main/java/friend/spring/web/controller/S3Controller.java +++ b/src/main/java/friend/spring/web/controller/S3Controller.java @@ -1,25 +1,20 @@ package friend.spring.web.controller; import friend.spring.apiPayload.ApiResponse; -import friend.spring.aws.s3.AmazonS3Manager; import friend.spring.service.S3Service; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestPart; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -@RequiredArgsConstructor @RestController +@RequiredArgsConstructor @RequestMapping("/uploadImage") public class S3Controller { private final S3Service s3Service; // 유저 이미지 올리기 @PostMapping(value = "", consumes = "multipart/form-data") - public ApiResponse uploadUserImage(@RequestPart(value = "file", required = false) MultipartFile file) { + public ApiResponse uploadUserImage(@RequestParam("file") MultipartFile file) { String url = s3Service.uploadUserImage(file); return ApiResponse.onSuccess(url); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 5334bb7..a059c0f 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -18,24 +18,24 @@ spring: auto: update default_batch_fetch_size: 1000 globally_quoted_identifiers: true - cloud: - aws: - s3: - bucket: solution-friend-bucket - path: - user: users - post: posts - report: reports - region: - static: ap-northeast-2 - stack: - auto: false - credentials: - accessKey: ${AWS_ACCESS_KEY_ID} - secretKey: ${AWS_SECRET_ACCESS_KEY} - logging: - level: - com: - amazonaws: - util: - EC2MetadataUtils: error \ No newline at end of file +cloud: + aws: + s3: + bucket: solution-friend-bucket + path: + user: users + post: posts + report: reports + region: + static: ap-northeast-2 + stack: + auto: false + credentials: + accessKey: ${AWS_ACCESS_KEY_ID} + secretKey: ${AWS_SECRET_ACCESS_KEY} +logging: + level: + com: + amazonaws: + util: + EC2MetadataUtils: error \ No newline at end of file From 39664addd3e70543b2480276d41c6ea543105e1d Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 23 Jan 2024 06:47:37 +0900 Subject: [PATCH 023/255] =?UTF-8?q?#8=20Chore:=20S3=20=EC=97=85=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=EC=8B=9C=20ContentType=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ .../friend/spring/aws/s3/AmazonS3Manager.java | 15 +++++++++++++-- src/main/java/friend/spring/config/S3Config.java | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/main/java/friend/spring/config/S3Config.java diff --git a/build.gradle b/build.gradle index b2b74ff..0f87939 100644 --- a/build.gradle +++ b/build.gradle @@ -41,6 +41,8 @@ dependencies { // S3 implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' + implementation platform('software.amazon.awssdk:bom:2.20.56') + implementation 'software.amazon.awssdk:s3' } tasks.named('test') { diff --git a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java index eb9a0c0..1c32fe3 100644 --- a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java +++ b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java @@ -2,7 +2,6 @@ import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectRequest; import friend.spring.config.AmazonConfig; import friend.spring.domain.Uuid; import friend.spring.repository.UuidRepository; @@ -10,6 +9,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; import java.io.IOException; @@ -20,6 +22,8 @@ public class AmazonS3Manager{ private final AmazonS3 amazonS3; + private final S3Client s3Client; + private final AmazonConfig amazonConfig; private final UuidRepository uuidRepository; @@ -28,7 +32,14 @@ public String uploadFile(String keyName, MultipartFile file){ ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentLength(file.getSize()); try { - amazonS3.putObject(new PutObjectRequest(amazonConfig.getBucket(), keyName, file.getInputStream(), metadata)); + PutObjectRequest putObjectRequest = PutObjectRequest.builder() + .bucket(amazonConfig.getBucket()) + .key(keyName) + .contentType(file.getContentType()) + .contentDisposition("inline") + .build(); + s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(file.getInputStream(), file.getSize())); + }catch (IOException e){ log.error("error at AmazonS3Manager uploadFile : {}", (Object) e.getStackTrace()); } diff --git a/src/main/java/friend/spring/config/S3Config.java b/src/main/java/friend/spring/config/S3Config.java new file mode 100644 index 0000000..466cced --- /dev/null +++ b/src/main/java/friend/spring/config/S3Config.java @@ -0,0 +1,15 @@ +package friend.spring.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +@Configuration +public class S3Config { + + @Bean + public S3Client defaultS3Client() { + return S3Client.builder().region(Region.AP_NORTHEAST_2).build(); + } +} From d6401990201f594378fc30f15ebdd28535e1ffee Mon Sep 17 00:00:00 2001 From: park sang woo Date: Thu, 18 Jan 2024 17:20:21 +0900 Subject: [PATCH 024/255] =?UTF-8?q?dependencies=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index ea26407..ef3fc09 100644 --- a/build.gradle +++ b/build.gradle @@ -29,6 +29,12 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'mysql:mysql-connector-java:8.0.35' + + //jwt + testImplementation 'org.springframework.security:spring-security-test' + implementation 'io.jsonwebtoken:jjwt-api:0.12.3' + implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' + implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' } tasks.named('test') { From a526eacccee89e943b00d2d8b07490b7f0d7c65e Mon Sep 17 00:00:00 2001 From: ls-rain Date: Thu, 18 Jan 2024 17:30:28 +0900 Subject: [PATCH 025/255] =?UTF-8?q?#3=20feat=20:=20Swagger=20=EC=84=B8?= =?UTF-8?q?=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 ++ .../friend/spring/config/SwaggerConfig.java | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/main/java/friend/spring/config/SwaggerConfig.java diff --git a/build.gradle b/build.gradle index ef3fc09..d9fd308 100644 --- a/build.gradle +++ b/build.gradle @@ -29,6 +29,9 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'mysql:mysql-connector-java:8.0.35' + implementation 'org.springdoc:springdoc-openapi-ui:1.6.15' + implementation 'io.springfox:springfox-swagger2:2.9.2' + implementation 'io.springfox:springfox-swagger-ui:2.9.2' //jwt testImplementation 'org.springframework.security:spring-security-test' diff --git a/src/main/java/friend/spring/config/SwaggerConfig.java b/src/main/java/friend/spring/config/SwaggerConfig.java new file mode 100644 index 0000000..0f4e9cc --- /dev/null +++ b/src/main/java/friend/spring/config/SwaggerConfig.java @@ -0,0 +1,37 @@ +package friend.spring.config; + +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; +import org.springframework.context.annotation.Bean; + +public class SwaggerConfig { + @Bean + public OpenAPI UMCstudyAPI() { + Info info = new Info() + .title("고민친구 Server API") + .description("고민친구 API 명세서") + .version("1.0.0"); + + String jwtSchemeName = "JWT TOKEN"; + // API 요청헤더에 인증정보 포함 + SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtSchemeName); + // SecuritySchemes 등록 + Components components = new Components() + .addSecuritySchemes(jwtSchemeName, new SecurityScheme() + .name(jwtSchemeName) + .type(SecurityScheme.Type.HTTP) // HTTP 방식 + .scheme("bearer") + .bearerFormat("JWT")); + + return new OpenAPI() + .addServersItem(new Server().url("/")) + .info(info) + .addSecurityItem(securityRequirement) + .components(components); + } +} + From c66589afff388b6e870e2f47a554c4fb7ace67a5 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:36:12 +0900 Subject: [PATCH 026/255] =?UTF-8?q?=EC=97=90=EB=9F=AC=EB=A1=9C=20=EC=9D=B8?= =?UTF-8?q?=ED=95=B4=208.0.35=20->=208.0.32=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9b205ed..fbd2998 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ dependencies { runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' - implementation 'mysql:mysql-connector-java:8.0.35' + implementation 'mysql:mysql-connector-java:8.0.32' implementation 'org.springdoc:springdoc-openapi-ui:1.6.15' implementation 'io.springfox:springfox-swagger2:2.9.2' implementation 'io.springfox:springfox-swagger-ui:2.9.2' From d6480f89d92438f19ecfb2c040ceabea0abd37b7 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:38:50 +0900 Subject: [PATCH 027/255] =?UTF-8?q?1.=20=ED=88=AC=ED=91=9C=ED=95=AD?= =?UTF-8?q?=EB=AA=A9=20=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD(Boolean=20-?= =?UTF-8?q?>=20String)=202.=20=ED=88=AC=ED=91=9C=ED=95=AD=EB=AA=A9=20List?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=203.=20=EC=97=B0=EA=B4=80?= =?UTF-8?q?=EA=B4=80=EA=B3=84=20=ED=8E=B8=EC=9D=98=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/domain/General_vote.java | 46 +++++++------------ 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/src/main/java/friend/spring/domain/General_vote.java b/src/main/java/friend/spring/domain/General_vote.java index e14a90c..1710fdb 100644 --- a/src/main/java/friend/spring/domain/General_vote.java +++ b/src/main/java/friend/spring/domain/General_vote.java @@ -4,6 +4,8 @@ import lombok.*; import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; @Entity @Getter @@ -15,35 +17,11 @@ public class General_vote extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false) - private Boolean select1; - - @Column(nullable = true) - private Boolean select2; - - @Column(nullable = true) - private Boolean select3; - - @Column(nullable = true) - private Boolean select4; - - @Column(nullable = true) - private Boolean select5; - - @Column(nullable = true) - private Boolean select6; - - @Column(nullable = true) - private Boolean select7; - - @Column(nullable = true) - private Boolean select8; - - @Column(nullable = true) - private Boolean select9; - - @Column(nullable = true) - private Boolean select10; + // 투표 옵션을 저장하는 리스트 + @ElementCollection + @CollectionTable(name = "general_vote_options", joinColumns = @JoinColumn(name = "general_vote_id")) + @Column(name = "option") + private List options = new ArrayList<>(); @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") @@ -52,4 +30,14 @@ public class General_vote extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "general_question_id") private General_question generalQuestion; + + @OneToOne(mappedBy = "generalVote", fetch = FetchType.LAZY, cascade = CascadeType.ALL) + private Post post; + + public void setPost(Post post) { + this.post = post; + if (post != null) { + post.setGeneralVote(this); + } + } } From 98891a9409f747871513b31b3d159ded00edf640 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:39:21 +0900 Subject: [PATCH 028/255] =?UTF-8?q?1.=20category=20=EC=B6=94=EA=B0=80=202.?= =?UTF-8?q?=20scrap=20=EC=B6=94=EA=B0=80=203.=20=EC=97=B0=EA=B4=80?= =?UTF-8?q?=EA=B4=80=EA=B3=84=20=ED=8E=B8=EC=9D=98=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Post.java | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 51ff324..f40795c 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -1,6 +1,7 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; +import friend.spring.domain.enums.PostCategory; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; @@ -38,6 +39,9 @@ public class Post extends BaseEntity { @Column private PostVoteType voteType; + @Enumerated(EnumType.STRING) + private PostCategory category; + @Column(nullable = true, length = 1000) private String file; @@ -51,6 +55,9 @@ public class Post extends BaseEntity { @Column(nullable = false) private Integer view; + @Column(nullable = false) + private Integer scrap; /////////////////////////////// + @Column(nullable = true) private Timestamp deadline; @@ -91,4 +98,21 @@ public class Post extends BaseEntity { @OneToMany(mappedBy = "post") private List gaugeQuestionList = new ArrayList<>(); + + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "general_vote_id") + private General_vote generalVote; + + public void setUser(User user){ + if(this.user != null) + user.getPostList().remove(this); + this.user = user; + user.getPostList().add(this); + } + + public void setGeneralVote(General_vote generalVote) { + this.generalVote=generalVote; + if(this.generalVote!=null) + generalVote.setPost(this); + } } From 887f6462dcc4688b54289e9e9ab2952104bbec22 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:39:38 +0900 Subject: [PATCH 029/255] =?UTF-8?q?=EC=9D=BC=EB=B0=98=20=ED=88=AC=ED=91=9C?= =?UTF-8?q?=20repository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/General_voteConverter.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/friend/spring/converter/General_voteConverter.java diff --git a/src/main/java/friend/spring/converter/General_voteConverter.java b/src/main/java/friend/spring/converter/General_voteConverter.java new file mode 100644 index 0000000..41466f1 --- /dev/null +++ b/src/main/java/friend/spring/converter/General_voteConverter.java @@ -0,0 +1,15 @@ +package friend.spring.converter; + +import friend.spring.domain.General_vote; + +import java.util.List; +import java.util.stream.Collectors; + +public class General_voteConverter { + + public static General_vote toGeneralVoteList(List pollOptions) { + return General_vote.builder() + .options(pollOptions) + .build(); + } +} \ No newline at end of file From add615c84be8b359d0370b0984a72a205ba56515 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:39:40 +0900 Subject: [PATCH 030/255] =?UTF-8?q?=EC=9D=BC=EB=B0=98=20=ED=88=AC=ED=91=9C?= =?UTF-8?q?=20repository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/repository/General_voteRepository.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/friend/spring/repository/General_voteRepository.java diff --git a/src/main/java/friend/spring/repository/General_voteRepository.java b/src/main/java/friend/spring/repository/General_voteRepository.java new file mode 100644 index 0000000..446cd31 --- /dev/null +++ b/src/main/java/friend/spring/repository/General_voteRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.General_vote; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface General_voteRepository extends JpaRepository { +} From ceb97d8fed90f4fd6ca456cf157342371a4046c8 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:40:00 +0900 Subject: [PATCH 031/255] =?UTF-8?q?category=20enum=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/enums/PostCategory.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/java/friend/spring/domain/enums/PostCategory.java diff --git a/src/main/java/friend/spring/domain/enums/PostCategory.java b/src/main/java/friend/spring/domain/enums/PostCategory.java new file mode 100644 index 0000000..9c2b960 --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/PostCategory.java @@ -0,0 +1,6 @@ +package friend.spring.domain.enums; + +//미정. 그냥 예시. +public enum PostCategory { + SPORTS, ANIMALS, FASHION +} From 7bcec93e66ddde946763ff83d4c9e05907e41cf6 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:40:17 +0900 Subject: [PATCH 032/255] post converter --- .../spring/converter/PostConverter.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/main/java/friend/spring/converter/PostConverter.java diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java new file mode 100644 index 0000000..38e8024 --- /dev/null +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -0,0 +1,80 @@ +package friend.spring.converter; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.domain.enums.PostCategory; +import friend.spring.domain.enums.PostType; +import friend.spring.domain.enums.PostVoteType; +import friend.spring.web.dto.PostRequestDTO; +import friend.spring.web.dto.PostResponseDTO; + +import java.time.LocalDateTime; + +import static friend.spring.domain.enums.PostType.*; + +public class PostConverter { + + public static PostResponseDTO.AddPostResultDTO toAddPostResultDTO(Post post) { + return PostResponseDTO.AddPostResultDTO.builder() + .postId(post.getId()) + .createdAt(LocalDateTime.now()) + .build(); + } + + public static Post toPost(PostRequestDTO.AddPostDTO request) { + PostType postType=null; + PostVoteType postVoteType=null; + PostCategory category=null; + + switch (request.getPostType()){ + case 1: + postType=PostType.NOT_VOTE; + break; + case 2: + postType=PostType.VOTE; + break; + case 3: + postType=PostType.REVIEW; + break; + } + + if(postType== VOTE) { + switch (request.getPostVoteType()) { + case 1: + postVoteType = PostVoteType.GENERAL; + break; + case 2: + postVoteType = PostVoteType.GAUGE; + break; + } + } + + switch (request.getCategory()){ + case 1: + category=PostCategory.SPORTS; + break; + case 2: + category=PostCategory.ANIMALS; + break; + case 3: + category=PostCategory.FASHION; + break; + } + + + return Post.builder() + .title(request.getTitle()) + .content(request.getContent()) + .postType(postType) + .category(category) + .voteType(postVoteType) + .file(request.getFile()) + .tag(request.getTag()) + .deadline(request.getDeadline()) + .point(request.getPoint()) + .view(0) + .scrap(0) + .build(); + } +} + + From 89f46dc8ee75c41bf50c4d14946bf62d5f587288 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:40:23 +0900 Subject: [PATCH 033/255] PostRepository --- src/main/java/friend/spring/repository/PostRepository.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/friend/spring/repository/PostRepository.java diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java new file mode 100644 index 0000000..8e82c21 --- /dev/null +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.Post; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostRepository extends JpaRepository { +} \ No newline at end of file From 91d443a4d89bf0f0fe1929aa82d6c5ef57bfd0cb Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:40:32 +0900 Subject: [PATCH 034/255] PostRequestDTO --- .../friend/spring/web/dto/PostRequestDTO.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/friend/spring/web/dto/PostRequestDTO.java diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java new file mode 100644 index 0000000..d3839cb --- /dev/null +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -0,0 +1,29 @@ +package friend.spring.web.dto; + +import friend.spring.domain.enums.PostType; +import friend.spring.domain.enums.PostVoteType; +import lombok.Getter; +import javax.validation.constraints.NotBlank; +import java.sql.Timestamp; +import java.time.LocalDate; +import java.util.List; + +public class PostRequestDTO { + @Getter + public static class AddPostDTO{ + @NotBlank + String title; + @NotBlank + String content; + @NotBlank + Integer postType; // 1: not vote, 2: vote, 3: review + Integer category; //미정 + Integer postVoteType;// 1: general, 2: gauge +// Integer parent_id; + List pollOption; + String file; + String tag; + Timestamp deadline; + Integer point; + } +} From 1e06002adffff5ee8e8fd1aa0c117b7b79a0d994 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:40:37 +0900 Subject: [PATCH 035/255] PostResponseDTO --- .../friend/spring/web/dto/PostResponseDTO.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/friend/spring/web/dto/PostResponseDTO.java diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java new file mode 100644 index 0000000..8faf54e --- /dev/null +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -0,0 +1,17 @@ +package friend.spring.web.dto; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +public class PostResponseDTO { + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class AddPostResultDTO { + Long postId; + LocalDateTime createdAt; + } +} \ No newline at end of file From e111b97d7c3b3cc1276d66b4d6ff331da5af4107 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:40:42 +0900 Subject: [PATCH 036/255] PostRestController --- .../web/controller/PostRestController.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/friend/spring/web/controller/PostRestController.java diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java new file mode 100644 index 0000000..c543e98 --- /dev/null +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -0,0 +1,25 @@ +package friend.spring.web.controller; +import friend.spring.apiPayload.ApiResponse; +import friend.spring.converter.PostConverter; +import friend.spring.domain.Post; +import friend.spring.service.PostService; +import friend.spring.web.dto.PostRequestDTO; +import friend.spring.web.dto.PostResponseDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +@RestController +@RequiredArgsConstructor +@Validated +@RequestMapping("/posts") +public class PostRestController { + private final PostService postService; + @PostMapping("/{user-id}") + public ApiResponse join(@RequestBody @Valid PostRequestDTO.AddPostDTO request, + @PathVariable(name="user-id")Long UserId){ + Post post= postService.joinPost(request,UserId); + return ApiResponse.onSuccess(PostConverter.toAddPostResultDTO(post)); + } +} From 400ba78e21c7a181bba1339b3d14b2bafb676f17 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:40:47 +0900 Subject: [PATCH 037/255] PostService --- src/main/java/friend/spring/service/PostService.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/friend/spring/service/PostService.java diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java new file mode 100644 index 0000000..95cbfb1 --- /dev/null +++ b/src/main/java/friend/spring/service/PostService.java @@ -0,0 +1,8 @@ +package friend.spring.service; + +import friend.spring.domain.Post; +import friend.spring.web.dto.PostRequestDTO; + +public interface PostService { + Post joinPost(PostRequestDTO.AddPostDTO request, Long userId); +} From f221c087700e4cb69cc21bce52b55600ff37fc08 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:40:49 +0900 Subject: [PATCH 038/255] PostService --- .../spring/service/PostServiceImpl.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/friend/spring/service/PostServiceImpl.java diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java new file mode 100644 index 0000000..6e34c07 --- /dev/null +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -0,0 +1,48 @@ +package friend.spring.service; + +import friend.spring.converter.General_voteConverter; +import friend.spring.converter.PostConverter; +import friend.spring.domain.General_vote; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.domain.enums.PostType; +import friend.spring.repository.General_voteRepository; +import friend.spring.repository.PostRepository; +import friend.spring.repository.UserRepository; +import friend.spring.web.dto.PostRequestDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +import static friend.spring.domain.enums.PostType.VOTE; + +@Service +@RequiredArgsConstructor +public class PostServiceImpl implements PostService{ + + private final PostRepository postRepository; + private final General_voteRepository generalVoteRepository; + private final UserRepository userRepository; + + @Override + @Transactional + public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { + Post newPost= PostConverter.toPost(request); + User user=userRepository.findById(userId) + .orElseThrow(()->new RuntimeException("\""+userId+"\"해당 유저가 없습니다")); + newPost.setUser(user); + + if(newPost.getPostType()==VOTE&&request.getPollOption()!=null){ + General_vote generalVote = General_voteConverter.toGeneralVoteList(request.getPollOption()); + newPost.setGeneralVote(generalVote); + + generalVoteRepository.save(generalVote); + + } + + return postRepository.save(newPost); + } +} From caabd5448271e6822cd053abd8181ced392ea55a Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:47:59 +0900 Subject: [PATCH 039/255] General_voteConverter --- src/main/java/friend/spring/converter/General_voteConverter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/friend/spring/converter/General_voteConverter.java b/src/main/java/friend/spring/converter/General_voteConverter.java index 41466f1..fac104f 100644 --- a/src/main/java/friend/spring/converter/General_voteConverter.java +++ b/src/main/java/friend/spring/converter/General_voteConverter.java @@ -3,7 +3,6 @@ import friend.spring.domain.General_vote; import java.util.List; -import java.util.stream.Collectors; public class General_voteConverter { From 1b0f4aac4d65e81a10b474b1a3d42ced82b343de Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:49:18 +0900 Subject: [PATCH 040/255] =?UTF-8?q?1.=20view&scrap=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=EA=B0=92=200=20=EC=84=A4=EC=A0=95=202.=20generalVote=EC=99=80?= =?UTF-8?q?=20=EC=96=91=EB=B0=A9=ED=96=A5=20=EA=B4=80=EA=B3=84=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95,=20=ED=8E=B8=EC=9D=98=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1=203.=20setUser=EB=9E=91=20=ED=8E=B8?= =?UTF-8?q?=EC=9D=98=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Post.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index f40795c..e0e1167 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -53,10 +53,10 @@ public class Post extends BaseEntity { private PostState state; @Column(nullable = false) - private Integer view; + private Integer view=0; @Column(nullable = false) - private Integer scrap; /////////////////////////////// + private Integer scrap=0; /////////////////////////////// @Column(nullable = true) private Timestamp deadline; From 776c981bbf74d42873499dbee0cfd3b27537041a Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:49:32 +0900 Subject: [PATCH 041/255] PostConverter --- src/main/java/friend/spring/converter/PostConverter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 38e8024..b653879 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -1,6 +1,5 @@ package friend.spring.converter; import friend.spring.domain.Post; -import friend.spring.domain.User; import friend.spring.domain.enums.PostCategory; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; From 0243a656832c5e40e99ee2db4c405191e3e50ccb Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:49:37 +0900 Subject: [PATCH 042/255] PostRequestDTO --- src/main/java/friend/spring/web/dto/PostRequestDTO.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index d3839cb..cebe651 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -1,11 +1,9 @@ package friend.spring.web.dto; -import friend.spring.domain.enums.PostType; -import friend.spring.domain.enums.PostVoteType; + import lombok.Getter; import javax.validation.constraints.NotBlank; import java.sql.Timestamp; -import java.time.LocalDate; import java.util.List; public class PostRequestDTO { From 9c9d518b5acc517d6f90955607279374924f0265 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 24 Jan 2024 12:49:42 +0900 Subject: [PATCH 043/255] PostService --- src/main/java/friend/spring/service/PostServiceImpl.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 6e34c07..f6f3330 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -5,7 +5,6 @@ import friend.spring.domain.General_vote; import friend.spring.domain.Post; import friend.spring.domain.User; -import friend.spring.domain.enums.PostType; import friend.spring.repository.General_voteRepository; import friend.spring.repository.PostRepository; import friend.spring.repository.UserRepository; @@ -14,8 +13,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.stream.Collectors; import static friend.spring.domain.enums.PostType.VOTE; From 6bc154573397f9172cd6c105cd674fb01c16f1bd Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Wed, 24 Jan 2024 15:45:09 +0900 Subject: [PATCH 044/255] =?UTF-8?q?#1=20Chore:=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=ED=95=B8=EB=93=A4=EB=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/apiPayload/ExceptionAdvice.java | 119 ++++++++++++++++++ .../spring/apiPayload/GeneralException.java | 21 ++++ .../apiPayload/code/status/ErrorStatus.java | 18 ++- .../apiPayload/handler/PostHandler.java | 10 ++ .../apiPayload/handler/UserHandler.java | 10 ++ .../spring/repository/PostRepository.java | 7 ++ .../friend/spring/service/PostService.java | 5 + .../spring/service/PostServiceImpl.java | 17 +++ .../friend/spring/service/UserService.java | 1 + .../spring/service/UserServiceImpl.java | 8 ++ 10 files changed, 210 insertions(+), 6 deletions(-) create mode 100644 src/main/java/friend/spring/apiPayload/ExceptionAdvice.java create mode 100644 src/main/java/friend/spring/apiPayload/GeneralException.java create mode 100644 src/main/java/friend/spring/apiPayload/handler/PostHandler.java create mode 100644 src/main/java/friend/spring/apiPayload/handler/UserHandler.java create mode 100644 src/main/java/friend/spring/repository/PostRepository.java create mode 100644 src/main/java/friend/spring/service/PostService.java create mode 100644 src/main/java/friend/spring/service/PostServiceImpl.java diff --git a/src/main/java/friend/spring/apiPayload/ExceptionAdvice.java b/src/main/java/friend/spring/apiPayload/ExceptionAdvice.java new file mode 100644 index 0000000..d11c334 --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/ExceptionAdvice.java @@ -0,0 +1,119 @@ +package friend.spring.apiPayload; + +import friend.spring.apiPayload.code.ErrorReasonDTO; +import friend.spring.apiPayload.code.status.ErrorStatus; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.context.request.ServletWebRequest; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; + +@Slf4j +@RestControllerAdvice(annotations = {RestController.class}) +public class ExceptionAdvice extends ResponseEntityExceptionHandler { + + + @org.springframework.web.bind.annotation.ExceptionHandler + public ResponseEntity validation(ConstraintViolationException e, WebRequest request) { + String errorMessage = e.getConstraintViolations().stream() + .map(constraintViolation -> constraintViolation.getMessage()) + .findFirst() + .orElseThrow(() -> new RuntimeException("ConstraintViolationException 추출 도중 에러 발생")); + + return handleExceptionInternalConstraint(e, ErrorStatus.valueOf(errorMessage), HttpHeaders.EMPTY,request); + } + + + @Override + public ResponseEntity handleMethodArgumentNotValid( + MethodArgumentNotValidException e, HttpHeaders headers, HttpStatus status, WebRequest request) { + + Map errors = new LinkedHashMap<>(); + + e.getBindingResult().getFieldErrors().stream() + .forEach(fieldError -> { + String fieldName = fieldError.getField(); + String errorMessage = Optional.ofNullable(fieldError.getDefaultMessage()).orElse(""); + errors.merge(fieldName, errorMessage, (existingErrorMessage, newErrorMessage) -> existingErrorMessage + ", " + newErrorMessage); + }); + + return handleExceptionInternalArgs(e,HttpHeaders.EMPTY,ErrorStatus.valueOf("_BAD_REQUEST"),request,errors); + } + + @org.springframework.web.bind.annotation.ExceptionHandler + public ResponseEntity exception(Exception e, WebRequest request) { + e.printStackTrace(); + + return handleExceptionInternalFalse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(),request, e.getMessage()); + } + + @ExceptionHandler(value = GeneralException.class) + public ResponseEntity onThrowException(GeneralException generalException, HttpServletRequest request) { + ErrorReasonDTO errorReasonHttpStatus = generalException.getErrorReasonHttpStatus(); + return handleExceptionInternal(generalException,errorReasonHttpStatus,null,request); + } + + private ResponseEntity handleExceptionInternal(Exception e, ErrorReasonDTO reason, + HttpHeaders headers, HttpServletRequest request) { + + ApiResponse body = ApiResponse.onFailure(reason.getCode(),reason.getMessage(),null); +// e.printStackTrace(); + + WebRequest webRequest = new ServletWebRequest(request); + return super.handleExceptionInternal( + e, + body, + headers, + reason.getHttpStatus(), + webRequest + ); + } + + private ResponseEntity handleExceptionInternalFalse(Exception e, ErrorStatus errorCommonStatus, + HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorPoint); + return super.handleExceptionInternal( + e, + body, + headers, + status, + request + ); + } + + private ResponseEntity handleExceptionInternalArgs(Exception e, HttpHeaders headers, ErrorStatus errorCommonStatus, + WebRequest request, Map errorArgs) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorArgs); + return super.handleExceptionInternal( + e, + body, + headers, + errorCommonStatus.getHttpStatus(), + request + ); + } + + private ResponseEntity handleExceptionInternalConstraint(Exception e, ErrorStatus errorCommonStatus, + HttpHeaders headers, WebRequest request) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), null); + return super.handleExceptionInternal( + e, + body, + headers, + errorCommonStatus.getHttpStatus(), + request + ); + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/apiPayload/GeneralException.java b/src/main/java/friend/spring/apiPayload/GeneralException.java new file mode 100644 index 0000000..0b235a9 --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/GeneralException.java @@ -0,0 +1,21 @@ +package friend.spring.apiPayload; + +import friend.spring.apiPayload.code.BaseErrorCode; +import friend.spring.apiPayload.code.ErrorReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class GeneralException extends RuntimeException { + + private BaseErrorCode code; + + public ErrorReasonDTO getErrorReason() { + return this.code.getReason(); + } + + public ErrorReasonDTO getErrorReasonHttpStatus(){ + return this.code.getReasonHttpStatus(); + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 8c9e09f..45d0b3c 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -11,15 +11,21 @@ public enum ErrorStatus implements BaseErrorCode { // 가장 일반적인 응답 - _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버 에러, 관리자에게 문의 바랍니다."), - _BAD_REQUEST(HttpStatus.BAD_REQUEST,"COMMON400","잘못된 요청입니다."), - _UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON401","인증이 필요합니다."), - _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."), - ; + _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON5000", "서버 에러, 관리자에게 문의 바랍니다."), + _BAD_REQUEST(HttpStatus.BAD_REQUEST,"COMMON4000","잘못된 요청입니다."), + _UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON4001","인증이 필요합니다."), + _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON4003", "금지된 요청입니다."), // 멤버 관련 응답 + USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USER4001", "사용자를 찾을 수 없습니다."), + + // 글 관련 응답 + POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "글을 찾을 수 없습니다."), - // ~~~ 관련 응답 .... + // 댓글 관련 응답 + COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), + + ; private final HttpStatus httpStatus; private final String code; diff --git a/src/main/java/friend/spring/apiPayload/handler/PostHandler.java b/src/main/java/friend/spring/apiPayload/handler/PostHandler.java new file mode 100644 index 0000000..66c4269 --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/handler/PostHandler.java @@ -0,0 +1,10 @@ +package friend.spring.apiPayload.handler; + +import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.code.BaseErrorCode; + +public class PostHandler extends GeneralException { + public PostHandler(BaseErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/friend/spring/apiPayload/handler/UserHandler.java b/src/main/java/friend/spring/apiPayload/handler/UserHandler.java new file mode 100644 index 0000000..06099f1 --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/handler/UserHandler.java @@ -0,0 +1,10 @@ +package friend.spring.apiPayload.handler; + +import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.code.BaseErrorCode; + +public class UserHandler extends GeneralException { + public UserHandler(BaseErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java new file mode 100644 index 0000000..f62091e --- /dev/null +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.Post; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java new file mode 100644 index 0000000..e0d317f --- /dev/null +++ b/src/main/java/friend/spring/service/PostService.java @@ -0,0 +1,5 @@ +package friend.spring.service; + +public interface PostService { + void checkPost(Boolean flag); +} diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java new file mode 100644 index 0000000..1633631 --- /dev/null +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -0,0 +1,17 @@ +package friend.spring.service; + +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.apiPayload.handler.UserHandler; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PostServiceImpl implements PostService { + @Override + public void checkPost(Boolean flag) { + if (!flag) { + throw new UserHandler(ErrorStatus.POST_NOT_FOUND); + } + } +} diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index 6d726cf..79edd2d 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -1,4 +1,5 @@ package friend.spring.service; public interface UserService { + void checkUser(Boolean flag); } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 7011cba..d2f8c8a 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -1,9 +1,17 @@ package friend.spring.service; +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.apiPayload.handler.UserHandler; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class UserServiceImpl implements UserService { + @Override + public void checkUser(Boolean flag) { + if (!flag) { + throw new UserHandler(ErrorStatus.USER_NOT_FOUND); + } + } } From e52b332bfe739e7a5592ccbb0702693cb4cc4217 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Wed, 24 Jan 2024 17:19:03 +0900 Subject: [PATCH 045/255] =?UTF-8?q?#19=20feat=20:=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80(=ED=99=88)=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/UserConverter.java | 14 +++++++++++ .../friend/spring/service/UserService.java | 5 ++++ .../spring/service/UserServiceImpl.java | 14 +++++++++++ .../web/controller/UserRestController.java | 17 +++++++++++++ .../friend/spring/web/dto/UserRequestDTO.java | 3 +++ .../spring/web/dto/UserResponseDTO.java | 25 +++++++++++++++++++ 6 files changed, 78 insertions(+) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 2d50095..86f1a40 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -1,4 +1,18 @@ package friend.spring.converter; +import friend.spring.domain.User; +import friend.spring.web.dto.UserResponseDTO; + public class UserConverter { + public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ + return UserResponseDTO.MyPageResDTO.builder() + .userPhoto(user.getImage()) + .userName(user.getName()) + .userPoint(user.getPoint()) + .userLevelInt(user.getLevel().getLike()) + .userLevelName(user.getLevel().getName()) + .userRecommend(user.getLike()) + .build(); + } + } diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index 6d726cf..df23e3f 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -1,4 +1,9 @@ package friend.spring.service; +import friend.spring.domain.User; + +import java.util.Optional; + public interface UserService { + Optional findUser(Long id); } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 7011cba..19dfd3d 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -1,9 +1,23 @@ package friend.spring.service; +import friend.spring.domain.User; +import friend.spring.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; @Service +@Transactional @RequiredArgsConstructor public class UserServiceImpl implements UserService { + + private final UserRepository userRepository; + + + @Override + public Optional findUser(Long id) { + return userRepository.findById(id); + } } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index fac613a..d3303e3 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -1,12 +1,29 @@ package friend.spring.web.controller; +import friend.spring.apiPayload.ApiResponse; +import friend.spring.converter.UserConverter; +import friend.spring.domain.Level; +import friend.spring.domain.User; +import friend.spring.service.UserService; +import friend.spring.web.dto.UserResponseDTO; import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Optional; + @RestController @RequiredArgsConstructor @RequestMapping("/user") public class UserRestController { + private final UserService userService; + + @GetMapping("/my-page") + public ApiResponse myPage(@RequestHeader(name = "id") Long userId){ + User user = userService.findUser(userId).get(); + return ApiResponse.onSuccess(UserConverter.toMypageResDTO(user)); + } } diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 089a5f4..b5c987f 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -1,4 +1,7 @@ package friend.spring.web.dto; +import lombok.Getter; + public class UserRequestDTO { + } diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index 6f17e26..c84e1c8 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -1,4 +1,29 @@ package friend.spring.web.dto; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + public class UserResponseDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class MyPageResDTO { + String userPhoto; + String userName; + Integer userPoint; + Integer userLevelInt; + String userLevelName; + Integer userRecommend; + } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class QuestionResDTO { + + } } From 74db0f229815f266c32fc5e109ebc49f80d24ab8 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Wed, 24 Jan 2024 18:00:38 +0900 Subject: [PATCH 046/255] =?UTF-8?q?#19=20feat=20:=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80(=ED=99=88)=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84(=EC=88=98=EC=A0=951=EC=B0=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/service/UserService.java | 2 +- src/main/java/friend/spring/service/UserServiceImpl.java | 9 +++++++-- .../friend/spring/web/controller/UserRestController.java | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index 8a458e5..5f31113 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -5,6 +5,6 @@ import java.util.Optional; public interface UserService { - Optional findUser(Long id); + User findMyPage(Long id); void checkUser(Boolean flag); } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 06e1cf1..a38b5fa 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -19,9 +19,14 @@ public class UserServiceImpl implements UserService { @Override - public Optional findUser(Long id) { - return userRepository.findById(id); + public User findMyPage(Long id) { + Optional user = userRepository.findById(id); + if(user.isEmpty()){ + throw new UserHandler(ErrorStatus.USER_NOT_FOUND); + } + return user.get(); } + @Override public void checkUser(Boolean flag) { if (!flag) { diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index d3303e3..944426c 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -22,8 +22,8 @@ public class UserRestController { private final UserService userService; @GetMapping("/my-page") - public ApiResponse myPage(@RequestHeader(name = "id") Long userId){ - User user = userService.findUser(userId).get(); - return ApiResponse.onSuccess(UserConverter.toMypageResDTO(user)); + public ApiResponse myPage(@RequestHeader(name = "id") Long userId) { + User Page = userService.findMyPage(userId); + return ApiResponse.onSuccess(UserConverter.toMypageResDTO(Page)); } } From 4d900ae238e80c80268a07f475474f19f431d544 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 26 Jan 2024 02:11:24 +0900 Subject: [PATCH 047/255] =?UTF-8?q?#1=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/CommentConverter.java | 24 +++++++ src/main/java/friend/spring/domain/User.java | 3 - .../spring/repository/CommentRepository.java | 7 ++ .../friend/spring/service/CommentService.java | 9 +++ .../spring/service/CommentServiceImpl.java | 67 +++++++++++++++++++ .../web/controller/CommentRestController.java | 31 +++++++++ .../spring/web/dto/CommentRequestDTO.java | 21 ++++++ .../spring/web/dto/CommentResponseDTO.java | 17 +++++ 8 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 src/main/java/friend/spring/converter/CommentConverter.java create mode 100644 src/main/java/friend/spring/repository/CommentRepository.java create mode 100644 src/main/java/friend/spring/service/CommentService.java create mode 100644 src/main/java/friend/spring/service/CommentServiceImpl.java create mode 100644 src/main/java/friend/spring/web/controller/CommentRestController.java create mode 100644 src/main/java/friend/spring/web/dto/CommentRequestDTO.java create mode 100644 src/main/java/friend/spring/web/dto/CommentResponseDTO.java diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java new file mode 100644 index 0000000..2a5ec78 --- /dev/null +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -0,0 +1,24 @@ +package friend.spring.converter; + +import friend.spring.domain.Comment; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.web.dto.CommentRequestDTO; +import friend.spring.web.dto.CommentResponseDTO; + +public class CommentConverter { + public static Comment toComment(CommentRequestDTO.commentCreateReq request, Post post, User user, Comment parentComment) { + return Comment.builder() + .user(user) + .post(post) + .content(request.getContent()) + .parentComment(parentComment) + .build(); + } + + public static CommentResponseDTO.commentCreateRes toCreateCommentRes(Comment comment) { + return CommentResponseDTO.commentCreateRes.builder() + .commentId(comment.getId()) + .build(); + } +} diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 193e5bd..3a81a58 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -23,9 +23,6 @@ public class User extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false, length = 15) - private String login_id; - @Column(nullable = false, length = 20) private String pw; diff --git a/src/main/java/friend/spring/repository/CommentRepository.java b/src/main/java/friend/spring/repository/CommentRepository.java new file mode 100644 index 0000000..7a92134 --- /dev/null +++ b/src/main/java/friend/spring/repository/CommentRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.Comment; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CommentRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java new file mode 100644 index 0000000..c10cb63 --- /dev/null +++ b/src/main/java/friend/spring/service/CommentService.java @@ -0,0 +1,9 @@ +package friend.spring.service; + +import friend.spring.domain.Comment; +import friend.spring.web.dto.CommentRequestDTO; + +public interface CommentService { + void checkComment(Boolean flag); + public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId); +} diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java new file mode 100644 index 0000000..a68d45b --- /dev/null +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -0,0 +1,67 @@ +package friend.spring.service; + +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.apiPayload.handler.UserHandler; +import friend.spring.converter.CommentConverter; +import friend.spring.domain.Comment; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.repository.CommentRepository; +import friend.spring.repository.PostRepository; +import friend.spring.repository.UserRepository; +import friend.spring.web.dto.CommentRequestDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = false) +public class CommentServiceImpl implements CommentService { + + private final CommentRepository commentRepository; + private final PostRepository postRepository; + private final UserRepository userRepository; + private final UserService userService; + private final PostService postService; + + @Override + public void checkComment(Boolean flag) { + if (!flag) { + throw new UserHandler(ErrorStatus.COMMENT_NOT_FOUND); + } + } + + @Override + public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId) { + Optional optionalPost = postRepository.findById(postId); + if (optionalPost.isEmpty()) { + postService.checkPost(false); + } + + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Comment parentComment = null; + Post post = optionalPost.get(); + User user = optionalUser.get(); + + // 대댓글인 경우 + if (request.getParentId() != null) { + Optional optionalParentComment = commentRepository.findById(request.getParentId()); + if (optionalParentComment.isEmpty()) { + checkComment(false); + } + + parentComment = optionalParentComment.get(); + } + + Comment comment = CommentConverter.toComment(request, post, user, parentComment); + + return commentRepository.save(comment); + } +} diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java new file mode 100644 index 0000000..a0cb401 --- /dev/null +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -0,0 +1,31 @@ +package friend.spring.web.controller; + +import friend.spring.apiPayload.ApiResponse; +import friend.spring.converter.CommentConverter; +import friend.spring.domain.Comment; +import friend.spring.service.CommentService; +import friend.spring.web.dto.CommentRequestDTO; +import friend.spring.web.dto.CommentResponseDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/posts") +public class CommentRestController { + + private final CommentService commentService; + + // 댓글 작성 + @PostMapping("/{post-id}/comment") + public ApiResponse createComment( + @PathVariable("post-id") Long postId, + @RequestBody CommentRequestDTO.commentCreateReq request, + @RequestHeader("userId") Long userId + ) { + Comment comment = commentService.createComment(postId, request, userId); + return ApiResponse.onSuccess(CommentConverter.toCreateCommentRes(comment)); + } +} diff --git a/src/main/java/friend/spring/web/dto/CommentRequestDTO.java b/src/main/java/friend/spring/web/dto/CommentRequestDTO.java new file mode 100644 index 0000000..5ad90d6 --- /dev/null +++ b/src/main/java/friend/spring/web/dto/CommentRequestDTO.java @@ -0,0 +1,21 @@ +package friend.spring.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +public class CommentRequestDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class commentCreateReq { + @NotBlank + String content; + Long parentId; + } +} diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java new file mode 100644 index 0000000..ba60d59 --- /dev/null +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -0,0 +1,17 @@ +package friend.spring.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class CommentResponseDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class commentCreateRes { + Long commentId; + } +} From c8ae536b4a11ee2a7ec4dc9d46de676aea36b976 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Fri, 26 Jan 2024 16:06:51 +0900 Subject: [PATCH 048/255] =?UTF-8?q?#19=20feat=20:=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80(=ED=99=88)=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84(=EC=88=98=EC=A0=95=202=EC=B0=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/web/dto/UserResponseDTO.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index c84e1c8..34880c0 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -19,11 +19,5 @@ public static class MyPageResDTO { String userLevelName; Integer userRecommend; } - @Builder - @Getter - @NoArgsConstructor - @AllArgsConstructor - public static class QuestionResDTO { - } } From 5d7182e9e9ccef501d79ec1c194fe09e5e1fb269 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Fri, 26 Jan 2024 16:06:51 +0900 Subject: [PATCH 049/255] =?UTF-8?q?#27=20feat=20:=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80(=ED=99=88)=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84(=EC=88=98=EC=A0=95=202=EC=B0=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/web/dto/UserResponseDTO.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index c84e1c8..34880c0 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -19,11 +19,5 @@ public static class MyPageResDTO { String userLevelName; Integer userRecommend; } - @Builder - @Getter - @NoArgsConstructor - @AllArgsConstructor - public static class QuestionResDTO { - } } From 34cb4272aaf8eb41c4b3111480d6769327b52085 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Fri, 26 Jan 2024 19:55:51 +0900 Subject: [PATCH 050/255] 1 --- .../apiPayload/code/status/ErrorStatus.java | 10 +++++++++- src/main/java/friend/spring/domain/User.java | 4 ++-- .../friend/spring/repository/UserRepository.java | 10 ++++++++++ src/main/resources/application.yml | 16 ++++++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 45d0b3c..aa409d6 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -16,8 +16,16 @@ public enum ErrorStatus implements BaseErrorCode { _UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON4001","인증이 필요합니다."), _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON4003", "금지된 요청입니다."), + // 멤버 관련 응답 - USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USER4001", "사용자를 찾을 수 없습니다."), + USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USER4001", "회원정보가 존재하지 않습니다."), + USERS_NOT_FOUND_EMAIL(HttpStatus.NOT_FOUND,"USER4010","가입 가능한 이메일입니다."), + USER_EXISTS_EMAIL(HttpStatus.NOT_ACCEPTABLE,"USER4002","이미 존재하는 메일 주소입니다"), + UNABLE_TO_SEND_EMAIL(HttpStatus.BAD_REQUEST, "USER4003", "이메일을 발송하지 못했습니다."), + ERR_MAKE_CODE(HttpStatus.BAD_REQUEST, "USER4004", "인증 코드 생성에 오류가 있습니다."), + INCORRECT_CODE(HttpStatus.UNAUTHORIZED, "USER4005", "인증 코드가 일치하지 않습니다."), + EMPTY_JWT(HttpStatus.BAD_REQUEST, "USER4006", "JWT를 입력해주세요."), + INVALID_JWT(HttpStatus.UNAUTHORIZED, "USER4007", "유효하지 않은 JWT입니다."), // 글 관련 응답 POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "글을 찾을 수 없습니다."), diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 193e5bd..02f9afe 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -23,8 +23,8 @@ public class User extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false, length = 15) - private String login_id; +// @Column(nullable = false, length = 15) +// private String login_id; @Column(nullable = false, length = 20) private String pw; diff --git a/src/main/java/friend/spring/repository/UserRepository.java b/src/main/java/friend/spring/repository/UserRepository.java index d002975..66c5105 100644 --- a/src/main/java/friend/spring/repository/UserRepository.java +++ b/src/main/java/friend/spring/repository/UserRepository.java @@ -4,6 +4,16 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface UserRepository extends JpaRepository { + + Optional findByEmail(String email); + + Optional findByEmailAndPassword(String email, String password); + + Optional findById(Long Id); + + boolean existsById(Long Id); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a059c0f..e2ebe58 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,20 @@ spring: + mail: + host: smtp.gmail.com + port: 587 + username: ${gamil.username} + password: ${gmail.password} + properties: + mail: + smtp: + auth: true + starttls: + enable: true + required: true + connectiontimeout: 5000 + timeout: 5000 + writetimeout: 5000 + auth-code-expiration-millis: 1800000 # 30 * 60 * 1000 == 30분 datasource: url: ${aws.db.url} username: ${aws.db.username} From dead250a4b3eed96949cb007a090d539c5e5334a Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 28 Jan 2024 15:43:56 +0900 Subject: [PATCH 051/255] =?UTF-8?q?#23=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=B6=94=EC=B2=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/CommentConverter.java | 16 +++++++++- .../spring/domain/mapping/Comment_like.java | 2 -- .../repository/CommentLikeRepository.java | 7 +++++ .../friend/spring/service/CommentService.java | 3 ++ .../spring/service/CommentServiceImpl.java | 30 ++++++++++++++++++- .../web/controller/CommentRestController.java | 16 ++++++++-- .../spring/web/dto/CommentResponseDTO.java | 8 +++++ 7 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 src/main/java/friend/spring/repository/CommentLikeRepository.java diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index 2a5ec78..65b56c4 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -3,6 +3,7 @@ import friend.spring.domain.Comment; import friend.spring.domain.Post; import friend.spring.domain.User; +import friend.spring.domain.mapping.Comment_like; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; @@ -16,9 +17,22 @@ public static Comment toComment(CommentRequestDTO.commentCreateReq request, Post .build(); } - public static CommentResponseDTO.commentCreateRes toCreateCommentRes(Comment comment) { + public static CommentResponseDTO.commentCreateRes toCommentCreateRes(Comment comment) { return CommentResponseDTO.commentCreateRes.builder() .commentId(comment.getId()) .build(); } + + public static Comment_like toCommentLike(Post post, Comment comment, User user) { + return Comment_like.builder() + .user(user) + .comment(comment) + .build(); + } + + public static CommentResponseDTO.commentLikeRes toCommentLikeRes(Comment_like comment_like) { + return CommentResponseDTO.commentLikeRes.builder() + .commentLikeId(comment_like.getId()) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/mapping/Comment_like.java b/src/main/java/friend/spring/domain/mapping/Comment_like.java index 1a6ca80..0e09b98 100644 --- a/src/main/java/friend/spring/domain/mapping/Comment_like.java +++ b/src/main/java/friend/spring/domain/mapping/Comment_like.java @@ -17,8 +17,6 @@ public class Comment_like extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private Integer point; - @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; diff --git a/src/main/java/friend/spring/repository/CommentLikeRepository.java b/src/main/java/friend/spring/repository/CommentLikeRepository.java new file mode 100644 index 0000000..2d411b3 --- /dev/null +++ b/src/main/java/friend/spring/repository/CommentLikeRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.mapping.Comment_like; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CommentLikeRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index c10cb63..8564ebb 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -1,9 +1,12 @@ package friend.spring.service; import friend.spring.domain.Comment; +import friend.spring.domain.mapping.Comment_like; import friend.spring.web.dto.CommentRequestDTO; public interface CommentService { void checkComment(Boolean flag); public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId); + + Comment_like likeComment(Long postId, Long commentId, Long userId); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index a68d45b..d681e8c 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -6,6 +6,8 @@ import friend.spring.domain.Comment; import friend.spring.domain.Post; import friend.spring.domain.User; +import friend.spring.domain.mapping.Comment_like; +import friend.spring.repository.CommentLikeRepository; import friend.spring.repository.CommentRepository; import friend.spring.repository.PostRepository; import friend.spring.repository.UserRepository; @@ -24,6 +26,7 @@ public class CommentServiceImpl implements CommentService { private final CommentRepository commentRepository; private final PostRepository postRepository; private final UserRepository userRepository; + private final CommentLikeRepository commentLikeRepository; private final UserService userService; private final PostService postService; @@ -54,7 +57,7 @@ public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq req if (request.getParentId() != null) { Optional optionalParentComment = commentRepository.findById(request.getParentId()); if (optionalParentComment.isEmpty()) { - checkComment(false); + this.checkComment(false); } parentComment = optionalParentComment.get(); @@ -64,4 +67,29 @@ public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq req return commentRepository.save(comment); } + + @Override + public Comment_like likeComment(Long postId, Long commentId, Long userId) { + Optional optionalPost = postRepository.findById(postId); + if (optionalPost.isEmpty()) { + postService.checkPost(false); + } + + Optional optionalComment = commentRepository.findById(commentId); + if (optionalComment.isEmpty()) { + this.checkComment(false); + } + + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Post post = optionalPost.get(); + Comment comment = optionalComment.get(); + User user = optionalUser.get(); + + Comment_like comment_like = CommentConverter.toCommentLike(post, comment, user); + return commentLikeRepository.save(comment_like); + } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index a0cb401..b438c77 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -3,14 +3,13 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.CommentConverter; import friend.spring.domain.Comment; +import friend.spring.domain.mapping.Comment_like; import friend.spring.service.CommentService; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; -import javax.validation.Valid; - @RestController @RequiredArgsConstructor @RequestMapping("/posts") @@ -26,6 +25,17 @@ public ApiResponse createComment( @RequestHeader("userId") Long userId ) { Comment comment = commentService.createComment(postId, request, userId); - return ApiResponse.onSuccess(CommentConverter.toCreateCommentRes(comment)); + return ApiResponse.onSuccess(CommentConverter.toCommentCreateRes(comment)); + } + + // 댓글 추천(좋아요) + @PostMapping("/{post-id}/comment/{comment-id}/like") + public ApiResponse likeComment( + @PathVariable("post-id") Long postId, + @PathVariable("comment-id") Long commentId, + @RequestHeader("userId") Long userId + ) { + Comment_like comment_like = commentService.likeComment(postId, commentId, userId); + return ApiResponse.onSuccess(CommentConverter.toCommentLikeRes(comment_like)); } } diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index ba60d59..e863dc8 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -14,4 +14,12 @@ public class CommentResponseDTO { public static class commentCreateRes { Long commentId; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class commentLikeRes { + Long commentLikeId; // 댓글-좋아요 아이디 + } } From 4e72b4add1db6a7e7380fad7034d0dff3d54e2a2 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 29 Jan 2024 10:27:58 +0900 Subject: [PATCH 052/255] =?UTF-8?q?#29=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C(page=20=EC=95=88=20=EC=93=B4=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/CommentConverter.java | 30 +++++++++++++++++++ .../spring/repository/CommentRepository.java | 7 +++++ .../friend/spring/service/CommentService.java | 6 ++++ .../spring/service/CommentServiceImpl.java | 30 +++++++++++++++++++ .../web/controller/CommentRestController.java | 23 ++++++++++++++ .../spring/web/dto/CommentResponseDTO.java | 20 +++++++++++++ 6 files changed, 116 insertions(+) diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index 65b56c4..6f574b6 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -7,6 +7,9 @@ import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; +import java.util.ArrayList; +import java.util.List; + public class CommentConverter { public static Comment toComment(CommentRequestDTO.commentCreateReq request, Post post, User user, Comment parentComment) { return Comment.builder() @@ -35,4 +38,31 @@ public static CommentResponseDTO.commentLikeRes toCommentLikeRes(Comment_like co .commentLikeId(comment_like.getId()) .build(); } + + public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment) { + Long parentCommentId = null; + if (comment.getParentComment() != null) { + parentCommentId = comment.getParentComment().getId(); + } + + List subComments = new ArrayList<>(); + if (comment.getSubCommentList() != null) { + for (Comment c : comment.getSubCommentList()) { + subComments.add(toCommentGetRes(c)); + } + } + + return CommentResponseDTO.commentGetRes.builder() + .commentId(comment.getId()) + .content(comment.getContent()) + .userId(comment.getUser().getId()) + .userNickname(comment.getUser().getNickname()) + .userImage(comment.getUser().getImage()) + .createdAt(comment.getCreatedAt()) + .updatedAt(comment.getUpdatedAt()) + .parentCommentId(parentCommentId) + .commentLike(comment.getCommentLikeList().size()) + .childrenComments(subComments) + .build(); + } } diff --git a/src/main/java/friend/spring/repository/CommentRepository.java b/src/main/java/friend/spring/repository/CommentRepository.java index 7a92134..800e904 100644 --- a/src/main/java/friend/spring/repository/CommentRepository.java +++ b/src/main/java/friend/spring/repository/CommentRepository.java @@ -1,7 +1,14 @@ package friend.spring.repository; import friend.spring.domain.Comment; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface CommentRepository extends JpaRepository { + List findAllByPostId(Long postId); + + Page findByPostId(Long postId, Pageable pageable); } diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index 8564ebb..06cdf31 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -3,10 +3,16 @@ import friend.spring.domain.Comment; import friend.spring.domain.mapping.Comment_like; import friend.spring.web.dto.CommentRequestDTO; +import friend.spring.web.dto.CommentResponseDTO; +import org.springframework.data.domain.Page; + +import java.util.List; public interface CommentService { void checkComment(Boolean flag); public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId); Comment_like likeComment(Long postId, Long commentId, Long userId); + + List getComments(Long postId, Integer page); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index d681e8c..0836903 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -12,10 +12,17 @@ import friend.spring.repository.PostRepository; import friend.spring.repository.UserRepository; import friend.spring.web.dto.CommentRequestDTO; +import friend.spring.web.dto.CommentResponseDTO; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Optional; @Service @@ -92,4 +99,27 @@ public Comment_like likeComment(Long postId, Long commentId, Long userId) { Comment_like comment_like = CommentConverter.toCommentLike(post, comment, user); return commentLikeRepository.save(comment_like); } + + @Override + public List getComments(Long postId, Integer page) { + Optional optionalPost = postRepository.findById(postId); + if (optionalPost.isEmpty()) { + postService.checkPost(false); + } + + Post post = optionalPost.get(); + List comments = post.getCommentList(); // 댓글 리스트 전체 조회 + + List commentGetResList = new ArrayList<>(); + + for (Comment comment : comments) { + CommentResponseDTO.commentGetRes commentGetResDto = CommentConverter.toCommentGetRes(comment); + + if (comment.getParentComment() == null) { // 루트댓글인 경우 + commentGetResList.add(commentGetResDto); + } + } + + return commentGetResList; // page로 주고 싶은데 어떻게 해야 할까? + } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index b438c77..43a1834 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -7,9 +7,16 @@ import friend.spring.service.CommentService; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController @RequiredArgsConstructor @RequestMapping("/posts") @@ -38,4 +45,20 @@ public ApiResponse likeComment( Comment_like comment_like = commentService.likeComment(postId, commentId, userId); return ApiResponse.onSuccess(CommentConverter.toCommentLikeRes(comment_like)); } + + // 댓글 조회 + @GetMapping("/{post-id}/comments") + @Operation(summary = "댓글 조회 API", description = "댓글을 조회하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "글 아이디, path variable 입니다!") + }) + public ApiResponse> getComments( + @PathVariable("post-id") Long postId, + @RequestParam("name = page") Integer page + ) { + return ApiResponse.onSuccess(commentService.getComments(postId, page)); + } } diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index e863dc8..94677fd 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -5,6 +5,9 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.time.LocalDateTime; +import java.util.List; + public class CommentResponseDTO { @Builder @@ -22,4 +25,21 @@ public static class commentCreateRes { public static class commentLikeRes { Long commentLikeId; // 댓글-좋아요 아이디 } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class commentGetRes { + Long commentId; + String content; + Long userId; + String userNickname; + String userImage; + LocalDateTime createdAt; + LocalDateTime updatedAt; + Long parentCommentId; + Integer commentLike; + List childrenComments; + } } From 71ea0ea0148162bace9bf05dcfc87ac64cd7bda3 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 29 Jan 2024 11:05:59 +0900 Subject: [PATCH 053/255] =?UTF-8?q?#29=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C(page=20=EC=B6=94=EA=B0=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/repository/CommentRepository.java | 4 +- .../friend/spring/service/CommentService.java | 2 +- .../spring/service/CommentServiceImpl.java | 50 ++++++++++++------- .../web/controller/CommentRestController.java | 8 +-- 4 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/main/java/friend/spring/repository/CommentRepository.java b/src/main/java/friend/spring/repository/CommentRepository.java index 800e904..6292aad 100644 --- a/src/main/java/friend/spring/repository/CommentRepository.java +++ b/src/main/java/friend/spring/repository/CommentRepository.java @@ -8,7 +8,5 @@ import java.util.List; public interface CommentRepository extends JpaRepository { - List findAllByPostId(Long postId); - - Page findByPostId(Long postId, Pageable pageable); + Page findByPostIdAndParentCommentIsNull(Long postId, Pageable pageable); } diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index 06cdf31..8c8f390 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -14,5 +14,5 @@ public interface CommentService { Comment_like likeComment(Long postId, Long commentId, Long userId); - List getComments(Long postId, Integer page); + Page getComments(Long postId, Integer page, Integer size); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 0836903..7d6bd3f 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -15,15 +15,14 @@ import friend.spring.web.dto.CommentResponseDTO; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -101,25 +100,38 @@ public Comment_like likeComment(Long postId, Long commentId, Long userId) { } @Override - public List getComments(Long postId, Integer page) { + public Page getComments(Long postId, Integer page, Integer size) { Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { postService.checkPost(false); } - Post post = optionalPost.get(); - List comments = post.getCommentList(); // 댓글 리스트 전체 조회 - - List commentGetResList = new ArrayList<>(); - - for (Comment comment : comments) { - CommentResponseDTO.commentGetRes commentGetResDto = CommentConverter.toCommentGetRes(comment); - - if (comment.getParentComment() == null) { // 루트댓글인 경우 - commentGetResList.add(commentGetResDto); - } - } - - return commentGetResList; // page로 주고 싶은데 어떻게 해야 할까? + Pageable pageable = PageRequest.of(page, size); + Page commentPage = commentRepository.findByPostIdAndParentCommentIsNull(postId, pageable); // 루트 댓글만 가져옴 + List commentGetResList = commentPage + .map(comment -> { + CommentResponseDTO.commentGetRes commentGetRes = CommentConverter.toCommentGetRes(comment); + return commentGetRes; + }) + .filter(Objects::nonNull) // null인 요소는 필터링 + .get() + .collect(Collectors.toList()); + + +// Post post = optionalPost.get(); +// List comments = post.getCommentList(); // 댓글 리스트 전체 조회 + +// List commentGetResList = new ArrayList<>(); +// +// for (Comment comment : comments) { +// CommentResponseDTO.commentGetRes commentGetResDto = CommentConverter.toCommentGetRes(comment); +// +// if (comment.getParentComment() == null) { // 루트댓글인 경우 +// commentGetResList.add(commentGetResDto); +// } +// } +// +// return commentGetResList; // page로 주고 싶은데 어떻게 해야 할까? + return new PageImpl<>(commentGetResList, pageable, commentPage.getTotalElements()); } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 43a1834..5f76d12 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -55,10 +55,12 @@ public ApiResponse likeComment( @Parameters({ @Parameter(name = "post-id", description = "글 아이디, path variable 입니다!") }) - public ApiResponse> getComments( + public ApiResponse> getComments( @PathVariable("post-id") Long postId, - @RequestParam("name = page") Integer page + @RequestParam(name = "page") Integer page, + @RequestParam(name = "size") Integer size + ) { - return ApiResponse.onSuccess(commentService.getComments(postId, page)); + return ApiResponse.onSuccess(commentService.getComments(postId, page, size)); } } From 884ada44ec502ff748b45d12e066fd5c0e578a7f Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 29 Jan 2024 11:12:38 +0900 Subject: [PATCH 054/255] =?UTF-8?q?#29=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20swagger=20=EC=84=A4=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/service/CommentServiceImpl.java | 15 --------------- .../web/controller/CommentRestController.java | 6 ++++-- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 7d6bd3f..fac56c1 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -117,21 +117,6 @@ public Page getComments(Long postId, Integer p .get() .collect(Collectors.toList()); - -// Post post = optionalPost.get(); -// List comments = post.getCommentList(); // 댓글 리스트 전체 조회 - -// List commentGetResList = new ArrayList<>(); -// -// for (Comment comment : comments) { -// CommentResponseDTO.commentGetRes commentGetResDto = CommentConverter.toCommentGetRes(comment); -// -// if (comment.getParentComment() == null) { // 루트댓글인 경우 -// commentGetResList.add(commentGetResDto); -// } -// } -// -// return commentGetResList; // page로 주고 싶은데 어떻게 해야 할까? return new PageImpl<>(commentGetResList, pageable, commentPage.getTotalElements()); } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 5f76d12..dd8378f 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -48,12 +48,14 @@ public ApiResponse likeComment( // 댓글 조회 @GetMapping("/{post-id}/comments") - @Operation(summary = "댓글 조회 API", description = "댓글을 조회하는 API입니다.") + @Operation(summary = "댓글 조회 API", description = "댓글을 조회하는 API입니다. ex) /posts/111/comments?page=0&size=10") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), }) @Parameters({ - @Parameter(name = "post-id", description = "글 아이디, path variable 입니다!") + @Parameter(name = "post-id", description = "path variable - 글 아이디 입니다!"), + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), + @Parameter(name = "size", description = "query string(RequestParam) - 루트댓글 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)") }) public ApiResponse> getComments( @PathVariable("post-id") Long postId, From a8dead280be14ecb0da370ea34e536ead489beb9 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 29 Jan 2024 16:22:35 +0900 Subject: [PATCH 055/255] =?UTF-8?q?#23=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=B6=94=EC=B2=9C(=EC=A2=8B=EC=95=84=EC=9A=94)=20=ED=95=B4?= =?UTF-8?q?=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20&=20Comme?= =?UTF-8?q?ntRestController=20swagger=20=EB=AA=85=EC=84=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 2 +- .../repository/CommentLikeRepository.java | 3 + .../friend/spring/service/CommentService.java | 3 + .../spring/service/CommentServiceImpl.java | 33 +++++++++++ .../web/controller/CommentRestController.java | 57 ++++++++++++++++++- 5 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 45d0b3c..a0c8de2 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -24,7 +24,7 @@ public enum ErrorStatus implements BaseErrorCode { // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), - + COMMENT_LIKE_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4002", "댓글에 대한 좋아요 데이터를 찾을 수 없습니다."), ; private final HttpStatus httpStatus; diff --git a/src/main/java/friend/spring/repository/CommentLikeRepository.java b/src/main/java/friend/spring/repository/CommentLikeRepository.java index 2d411b3..3965a0c 100644 --- a/src/main/java/friend/spring/repository/CommentLikeRepository.java +++ b/src/main/java/friend/spring/repository/CommentLikeRepository.java @@ -3,5 +3,8 @@ import friend.spring.domain.mapping.Comment_like; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface CommentLikeRepository extends JpaRepository { + Optional findByCommentIdAndUserId(Long commentId, Long userId); } diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index 8c8f390..dd3a8d1 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -10,9 +10,12 @@ public interface CommentService { void checkComment(Boolean flag); + void checkCommentLike(Boolean flag); public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId); Comment_like likeComment(Long postId, Long commentId, Long userId); Page getComments(Long postId, Integer page, Integer size); + + void dislikeComment(Long postId, Long commentId, Long userId); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index fac56c1..eee9e78 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -43,6 +43,13 @@ public void checkComment(Boolean flag) { } } + @Override + public void checkCommentLike(Boolean flag) { + if (!flag) { + throw new UserHandler(ErrorStatus.COMMENT_LIKE_NOT_FOUND); + } + } + @Override public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId) { Optional optionalPost = postRepository.findById(postId); @@ -119,4 +126,30 @@ public Page getComments(Long postId, Integer p return new PageImpl<>(commentGetResList, pageable, commentPage.getTotalElements()); } + + @Override + public void dislikeComment(Long postId, Long commentId, Long userId) { + Optional optionalPost = postRepository.findById(postId); + if (optionalPost.isEmpty()) { + postService.checkPost(false); + } + + Optional optionalComment = commentRepository.findById(commentId); + if (optionalComment.isEmpty()) { + this.checkComment(false); + } + + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Optional optionalComment_like = commentLikeRepository.findByCommentIdAndUserId(commentId, userId); + if (optionalComment_like.isEmpty()) { + this.checkCommentLike(false); + } + + Comment_like comment_like = optionalComment_like.get(); + commentLikeRepository.delete(comment_like); + } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index dd8378f..c46d73f 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -10,9 +10,12 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -26,6 +29,17 @@ public class CommentRestController { // 댓글 작성 @PostMapping("/{post-id}/comment") + @Operation(summary = "댓글 작성 API", description = "댓글 작성하는 API입니다. ex) /posts/1/comment") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, (부모 루트) 댓글을 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + }) public ApiResponse createComment( @PathVariable("post-id") Long postId, @RequestBody CommentRequestDTO.commentCreateReq request, @@ -37,6 +51,18 @@ public ApiResponse createComment( // 댓글 추천(좋아요) @PostMapping("/{post-id}/comment/{comment-id}/like") + @Operation(summary = "댓글 추천(좋아요) 생성 API", description = "댓글 추천(좋아요) 생성하는 API입니다. ex) /posts/1/comment/1/like") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "comment-id", description = "path variable - 댓글 아이디"), + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + }) public ApiResponse likeComment( @PathVariable("post-id") Long postId, @PathVariable("comment-id") Long commentId, @@ -46,16 +72,41 @@ public ApiResponse likeComment( return ApiResponse.onSuccess(CommentConverter.toCommentLikeRes(comment_like)); } + // 댓글 추천(좋아요) 해제 + @PostMapping("/{post-id}/comment/{comment-id}/like/del") + @Operation(summary = "댓글 추천(좋아요) 해제 API", description = "댓글 추천(좋아요) 해제하는 API입니다. ex) /posts/1/comment/1/like/del") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4002",description = "NOT_FOUND, 댓글에 대한 좋아요 데이터를 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "comment-id", description = "path variable - 댓글 아이디"), + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + }) + public ApiResponse dislikeComment( + @PathVariable("post-id") Long postId, + @PathVariable("comment-id") Long commentId, + @RequestHeader("userId") Long userId + ) { + commentService.dislikeComment(postId, commentId, userId); + return ApiResponse.onSuccess(null); + } + // 댓글 조회 @GetMapping("/{post-id}/comments") @Operation(summary = "댓글 조회 API", description = "댓글을 조회하는 API입니다. ex) /posts/111/comments?page=0&size=10") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), }) @Parameters({ - @Parameter(name = "post-id", description = "path variable - 글 아이디 입니다!"), - @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), - @Parameter(name = "size", description = "query string(RequestParam) - 루트댓글 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)") + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), + @Parameter(name = "size", description = "query string(RequestParam) - 루트댓글 몇 개씩 불러올지 개수를 세는 변수 (1 이상 자연수로 설정)") }) public ApiResponse> getComments( @PathVariable("post-id") Long postId, From 46c01f898db50d28fa6bc5fa6d3b57006963b519 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 29 Jan 2024 19:12:04 +0900 Subject: [PATCH 056/255] =?UTF-8?q?#30=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=B1=84=ED=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 4 ++ .../spring/converter/CommentConverter.java | 16 +++++ .../repository/CommentChoiceRepository.java | 10 +++ .../friend/spring/service/CommentService.java | 5 ++ .../spring/service/CommentServiceImpl.java | 65 +++++++++++++++++-- .../friend/spring/service/PostService.java | 1 + .../spring/service/PostServiceImpl.java | 7 ++ .../web/controller/CommentRestController.java | 27 ++++++++ .../spring/web/dto/CommentResponseDTO.java | 9 +++ 9 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 src/main/java/friend/spring/repository/CommentChoiceRepository.java diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index a0c8de2..dd1672d 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -21,10 +21,14 @@ public enum ErrorStatus implements BaseErrorCode { // 글 관련 응답 POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "글을 찾을 수 없습니다."), + NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "POST4002", "올바른 사용자(글 작성자)가 아닙니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), COMMENT_LIKE_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4002", "댓글에 대한 좋아요 데이터를 찾을 수 없습니다."), + COMMENT_CHOICE_OVER_ONE(HttpStatus.BAD_REQUEST, "COMMENT4003", "댓글 채택은 1개 댓글에 대해서만 가능합니다."), + COMMENT_SELECT_MYSELF(HttpStatus.BAD_REQUEST, "COMMENT4004", "자기 자신은 채택할 수 없습니다."), + ; private final HttpStatus httpStatus; diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index 6f574b6..f114008 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -3,6 +3,7 @@ import friend.spring.domain.Comment; import friend.spring.domain.Post; import friend.spring.domain.User; +import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; @@ -65,4 +66,19 @@ public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment) .childrenComments(subComments) .build(); } + + public static Comment_choice toCommentChoice(Post post, Comment comment) { + return Comment_choice.builder() + .point(post.getPoint()) + .post(post) + .comment(comment) + .build(); + } + + public static CommentResponseDTO.commentSelectRes toCommentSelectRes(Comment_choice comment_choice) { + return CommentResponseDTO.commentSelectRes.builder() + .commentChoiceId(comment_choice.getId()) + .point(comment_choice.getPoint()) + .build(); + } } diff --git a/src/main/java/friend/spring/repository/CommentChoiceRepository.java b/src/main/java/friend/spring/repository/CommentChoiceRepository.java new file mode 100644 index 0000000..e246cc3 --- /dev/null +++ b/src/main/java/friend/spring/repository/CommentChoiceRepository.java @@ -0,0 +1,10 @@ +package friend.spring.repository; + +import friend.spring.domain.mapping.Comment_choice; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface CommentChoiceRepository extends JpaRepository { + Optional findByPostId(Long postId); +} diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index dd3a8d1..fc0d98f 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -1,6 +1,7 @@ package friend.spring.service; import friend.spring.domain.Comment; +import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; @@ -11,6 +12,8 @@ public interface CommentService { void checkComment(Boolean flag); void checkCommentLike(Boolean flag); + void checkCommentChoice(Boolean flag); + void checkSelectCommentAnotherUser(Boolean flag); public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId); Comment_like likeComment(Long postId, Long commentId, Long userId); @@ -18,4 +21,6 @@ public interface CommentService { Page getComments(Long postId, Integer page, Integer size); void dislikeComment(Long postId, Long commentId, Long userId); + + Comment_choice selectComment(Long postId, Long commentId, Long userId); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index eee9e78..d798d47 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -6,11 +6,9 @@ import friend.spring.domain.Comment; import friend.spring.domain.Post; import friend.spring.domain.User; +import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; -import friend.spring.repository.CommentLikeRepository; -import friend.spring.repository.CommentRepository; -import friend.spring.repository.PostRepository; -import friend.spring.repository.UserRepository; +import friend.spring.repository.*; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; import lombok.RequiredArgsConstructor; @@ -33,6 +31,7 @@ public class CommentServiceImpl implements CommentService { private final PostRepository postRepository; private final UserRepository userRepository; private final CommentLikeRepository commentLikeRepository; + private final CommentChoiceRepository commentChoiceRepository; private final UserService userService; private final PostService postService; @@ -50,6 +49,20 @@ public void checkCommentLike(Boolean flag) { } } + @Override + public void checkCommentChoice(Boolean flag) { + if (!flag) { + throw new UserHandler(ErrorStatus.COMMENT_CHOICE_OVER_ONE); + } + } + + @Override + public void checkSelectCommentAnotherUser(Boolean flag) { + if (!flag) { + throw new UserHandler(ErrorStatus.COMMENT_SELECT_MYSELF); + } + } + @Override public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId) { Optional optionalPost = postRepository.findById(postId); @@ -152,4 +165,48 @@ public void dislikeComment(Long postId, Long commentId, Long userId) { Comment_like comment_like = optionalComment_like.get(); commentLikeRepository.delete(comment_like); } + + @Override + public Comment_choice selectComment(Long postId, Long commentId, Long userId) { + Optional optionalPost = postRepository.findById(postId); + if (optionalPost.isEmpty()) { + postService.checkPost(false); + } + + Optional optionalComment = commentRepository.findById(commentId); + if (optionalComment.isEmpty()) { + this.checkComment(false); + } + + Optional optionalUser = userRepository.findById(userId); + // 이 사용자가 존재하는지 확인 + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Post post = optionalPost.get(); + Comment comment = optionalComment.get(); + User user = optionalUser.get(); + + // 로그인한 사용자가 이 글의 작성자인지 확인 + if (!Objects.equals(user.getId(), post.getUser().getId())) { + // 작성자가 아닌 경우 -> 에러 반환 + postService.checkPostWriterUser(false); + } + + // 자기 자신을 채택했는지 확인 + if (Objects.equals(user.getId(), comment.getUser().getId())) { + this.checkSelectCommentAnotherUser(false); + } + + Optional optionalComment_choice = commentChoiceRepository.findByPostId(postId); + if (!optionalComment_choice.isEmpty()) { // 이미 1명 채택을 한 상태이므로 에러로 반환 + this.checkCommentChoice(false); + } + + Comment_choice comment_choice = CommentConverter.toCommentChoice(post, comment); + return commentChoiceRepository.save(comment_choice); + } + + } diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index e0d317f..a621d9b 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -2,4 +2,5 @@ public interface PostService { void checkPost(Boolean flag); + void checkPostWriterUser(Boolean flag); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 1633631..9cc052b 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -14,4 +14,11 @@ public void checkPost(Boolean flag) { throw new UserHandler(ErrorStatus.POST_NOT_FOUND); } } + + @Override + public void checkPostWriterUser(Boolean flag) { + if (!flag) { + throw new UserHandler(ErrorStatus.NOT_CORRECT_USER); + } + } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index c46d73f..945556c 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -3,6 +3,7 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.CommentConverter; import friend.spring.domain.Comment; +import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.service.CommentService; import friend.spring.web.dto.CommentRequestDTO; @@ -116,4 +117,30 @@ public ApiResponse> getComments( ) { return ApiResponse.onSuccess(commentService.getComments(postId, page, size)); } + + // 댓글 채택 + @PostMapping("/{post-id}/comment/{comment-id}/choice") + @Operation(summary = "댓글 채택 API", description = "댓글 채택 데이터를 생성하는 API입니다. ex) /posts/1/comment/1/choice") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4002",description = "BAD_REQUEST, 올바른 사용자(글 작성자)가 아닙니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4003",description = "BAD_REQUEST, 댓글 채택은 1개 댓글에 대해서만 가능합니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4004",description = "BAD_REQUEST, 자기 자신은 채택할 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "comment-id", description = "path variable - 댓글 아이디"), + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + }) + public ApiResponse selectComment( + @PathVariable("post-id") Long postId, + @PathVariable("comment-id") Long commentId, + @RequestHeader("userId") Long userId + ) { + Comment_choice comment_choice = commentService.selectComment(postId, commentId, userId); + return ApiResponse.onSuccess(CommentConverter.toCommentSelectRes(comment_choice)); + } } diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index 94677fd..f43517d 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -42,4 +42,13 @@ public static class commentGetRes { Integer commentLike; List childrenComments; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class commentSelectRes { + Long commentChoiceId; + Integer point; + } } From a2bb3ede4ebef4645cc509cb30e8808b7e64d3ca Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:33:14 +0900 Subject: [PATCH 057/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84Gauge=5Fquestion=20->=20Gauge=5Fpoll?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/domain/{Gauge_question.java => Gauge_poll.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/friend/spring/domain/{Gauge_question.java => Gauge_poll.java} (93%) diff --git a/src/main/java/friend/spring/domain/Gauge_question.java b/src/main/java/friend/spring/domain/Gauge_poll.java similarity index 93% rename from src/main/java/friend/spring/domain/Gauge_question.java rename to src/main/java/friend/spring/domain/Gauge_poll.java index 472496a..aa084ad 100644 --- a/src/main/java/friend/spring/domain/Gauge_question.java +++ b/src/main/java/friend/spring/domain/Gauge_poll.java @@ -12,7 +12,7 @@ @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor -public class Gauge_question extends BaseEntity { +public class Gauge_poll extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; From 4a9db588a804c216e8da259ae3836b9f67477ea1 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:33:29 +0900 Subject: [PATCH 058/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84Gauge=5Fquestion=20->=20Gauge=5Fpoll?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Gauge_vote.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/domain/Gauge_vote.java b/src/main/java/friend/spring/domain/Gauge_vote.java index 3181006..3b041af 100644 --- a/src/main/java/friend/spring/domain/Gauge_vote.java +++ b/src/main/java/friend/spring/domain/Gauge_vote.java @@ -24,5 +24,5 @@ public class Gauge_vote extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "gauge_question_id") - private Gauge_question gaugeQuestion; + private Gauge_poll gaugeQuestion; } From c59cb44d5bf07d9812355e6be1e9b8c902a27591 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:34:35 +0900 Subject: [PATCH 059/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=20db=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20post=EC=99=80=20=EC=9D=BC=EB=8C=80?= =?UTF-8?q?=EC=9D=BC,=20candidate=EC=99=80=20=EC=9D=BC=EB=8C=80=EB=8B=A4?= =?UTF-8?q?=20=EC=84=A4=EA=B3=84.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/domain/General_poll.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/java/friend/spring/domain/General_poll.java diff --git a/src/main/java/friend/spring/domain/General_poll.java b/src/main/java/friend/spring/domain/General_poll.java new file mode 100644 index 0000000..5eb3b5e --- /dev/null +++ b/src/main/java/friend/spring/domain/General_poll.java @@ -0,0 +1,43 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import lombok.*; + +import javax.persistence.*; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class General_poll extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = true) + private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "general_vote_id") + private General_vote generalVote; + + @OneToOne(mappedBy = "generalPoll", cascade = CascadeType.ALL) + private Post post; + + @OneToMany(mappedBy = "generalPoll",cascade = CascadeType.ALL) + private List candidateList=new ArrayList<>(); + + public void setPost(Post post) { + this.post = post; + } + +} From 3b63e7ead5d4642a0f7702ee877dff1b9a5e18b4 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:35:42 +0900 Subject: [PATCH 060/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=20generalPoll?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/repository/General_PollRepository.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/friend/spring/repository/General_PollRepository.java diff --git a/src/main/java/friend/spring/repository/General_PollRepository.java b/src/main/java/friend/spring/repository/General_PollRepository.java new file mode 100644 index 0000000..5154ea1 --- /dev/null +++ b/src/main/java/friend/spring/repository/General_PollRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.General_poll; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface General_PollRepository extends JpaRepository { +} From 7ca426318c710c4dfe3549f6a4a52accbbc4785b Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:36:11 +0900 Subject: [PATCH 061/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=20db=EC=84=A4?= =?UTF-8?q?=EA=B3=84=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/domain/General_question.java | 86 ------------------- 1 file changed, 86 deletions(-) delete mode 100644 src/main/java/friend/spring/domain/General_question.java diff --git a/src/main/java/friend/spring/domain/General_question.java b/src/main/java/friend/spring/domain/General_question.java deleted file mode 100644 index 92cdec9..0000000 --- a/src/main/java/friend/spring/domain/General_question.java +++ /dev/null @@ -1,86 +0,0 @@ -package friend.spring.domain; - -import friend.spring.domain.common.BaseEntity; -import lombok.*; - -import javax.persistence.*; -import java.util.ArrayList; -import java.util.List; - -@Entity -@Getter -@Builder -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -public class General_question extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(nullable = false) - private String candidate1; - - @Column(nullable = true) - private String candidate2; - - @Column(nullable = true) - private String candidate3; - - @Column(nullable = true) - private String candidate4; - - @Column(nullable = true) - private String candidate5; - - @Column(nullable = true) - private String candidate6; - - @Column(nullable = true) - private String candidate7; - - @Column(nullable = true) - private String candidate8; - - @Column(nullable = true) - private String candidate9; - - @Column(nullable = true) - private String candidate10; - - @Column(nullable = true) - private String c1_img; - - @Column(nullable = true) - private String c2_img; - - @Column(nullable = true) - private String c3_img; - - @Column(nullable = true) - private String c4_img; - - @Column(nullable = true) - private String c5_img; - - @Column(nullable = true) - private String c6_img; - - @Column(nullable = true) - private String c7_img; - - @Column(nullable = true) - private String c8_img; - - @Column(nullable = true) - private String c9_img; - - @Column(nullable = true) - private String c10_img; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "post_id") - private Post post; - - @OneToMany(mappedBy = "generalQuestion") - private List generalVoteList = new ArrayList<>(); -} From 6640e7a8bf6ed740c5244db9ed7e4cd280558778 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:36:52 +0900 Subject: [PATCH 062/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=201.=20db=EC=84=A4?= =?UTF-8?q?=EA=B3=84=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=ED=88=AC=ED=91=9C?= =?UTF-8?q?=ED=95=AD=EB=AA=A9=20list=EB=A1=9C=20=EC=B2=98=EB=A6=AC=20=20?= =?UTF-8?q?=20=20=20=202.=20=EC=97=B0=EA=B4=80=EA=B4=80=EA=B3=84=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/domain/General_vote.java | 83 +++++++++++++++---- 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/src/main/java/friend/spring/domain/General_vote.java b/src/main/java/friend/spring/domain/General_vote.java index 1710fdb..662c795 100644 --- a/src/main/java/friend/spring/domain/General_vote.java +++ b/src/main/java/friend/spring/domain/General_vote.java @@ -17,27 +17,74 @@ public class General_vote extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - // 투표 옵션을 저장하는 리스트 - @ElementCollection - @CollectionTable(name = "general_vote_options", joinColumns = @JoinColumn(name = "general_vote_id")) - @Column(name = "option") - private List options = new ArrayList<>(); + @Column(nullable = false) + private String candidate1; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; + @Column(nullable = true) + private String candidate2; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "general_question_id") - private General_question generalQuestion; + @Column(nullable = true) + private String candidate3; + + @Column(nullable = true) + private String candidate4; + + @Column(nullable = true) + private String candidate5; + + @Column(nullable = true) + private String candidate6; + + @Column(nullable = true) + private String candidate7; + + @Column(nullable = true) + private String candidate8; + + @Column(nullable = true) + private String candidate9; + + @Column(nullable = true) + private String candidate10; + + @Column(nullable = true) + private String c1_img; + + @Column(nullable = true) + private String c2_img; - @OneToOne(mappedBy = "generalVote", fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @Column(nullable = true) + private String c3_img; + + @Column(nullable = true) + private String c4_img; + + @Column(nullable = true) + private String c5_img; + + @Column(nullable = true) + private String c6_img; + + @Column(nullable = true) + private String c7_img; + + @Column(nullable = true) + private String c8_img; + + @Column(nullable = true) + private String c9_img; + + @Column(nullable = true) + private String c10_img; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") private Post post; - public void setPost(Post post) { - this.post = post; - if (post != null) { - post.setGeneralVote(this); - } - } + @OneToMany(mappedBy = "generalVote") + private List generalPollList = new ArrayList<>(); + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; } From cca09bde0a0cd0669e2649465e8ddc6d34e8d128 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:37:06 +0900 Subject: [PATCH 063/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=20generalPoll?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/converter/General_voteConverter.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/friend/spring/converter/General_voteConverter.java b/src/main/java/friend/spring/converter/General_voteConverter.java index fac104f..b7e2fc3 100644 --- a/src/main/java/friend/spring/converter/General_voteConverter.java +++ b/src/main/java/friend/spring/converter/General_voteConverter.java @@ -1,14 +1,16 @@ package friend.spring.converter; -import friend.spring.domain.General_vote; +import friend.spring.domain.Candidate; +import friend.spring.domain.General_poll; +import friend.spring.web.dto.PollOptionDTO; import java.util.List; public class General_voteConverter { - public static General_vote toGeneralVoteList(List pollOptions) { - return General_vote.builder() - .options(pollOptions) + public static General_poll toGeneralVoteList(List pollOptions) { + return General_poll.builder() + .candidateList(pollOptions) .build(); } } \ No newline at end of file From ed9898c95bc7625167d632c2f0e78777f195800b Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:37:22 +0900 Subject: [PATCH 064/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/repository/General_voteRepository.java | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 src/main/java/friend/spring/repository/General_voteRepository.java diff --git a/src/main/java/friend/spring/repository/General_voteRepository.java b/src/main/java/friend/spring/repository/General_voteRepository.java deleted file mode 100644 index 446cd31..0000000 --- a/src/main/java/friend/spring/repository/General_voteRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package friend.spring.repository; - -import friend.spring.domain.General_vote; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface General_voteRepository extends JpaRepository { -} From a13677afa57f28f29a348cb22c891e9aa7ff917d Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:38:24 +0900 Subject: [PATCH 065/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=201.=20file?= =?UTF-8?q?=ED=95=AD=EB=AA=A9=20=EC=82=AD=EC=A0=9C=20=20=20=20=20=202.=20s?= =?UTF-8?q?crap=20=EC=82=AD=EC=A0=9C=20=20=20=20=20=203.=20tag=20list?= =?UTF-8?q?=EB=A1=9C=20=EC=B2=98=EB=A6=AC(db=EC=97=90=EC=84=9C=20=EC=83=88?= =?UTF-8?q?=EB=A1=9C=EC=9A=B4=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1)=20=20=20=20=20=204.=20=EB=B6=80=EB=AA=A8=EA=B8=80,?= =?UTF-8?q?=20=EC=9D=BC=EB=B0=98=ED=88=AC=ED=91=9C,=20tag=20=EC=97=B0?= =?UTF-8?q?=EA=B4=80=EA=B4=80=EA=B3=84=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Post.java | 49 ++++++++++++-------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index e0e1167..3be1d34 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -11,7 +11,6 @@ import lombok.*; import javax.persistence.*; -import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; @@ -42,11 +41,12 @@ public class Post extends BaseEntity { @Enumerated(EnumType.STRING) private PostCategory category; - @Column(nullable = true, length = 1000) - private String file; +// @Column(nullable = true, length = 1000) +// private String file; + @ElementCollection @Column(nullable = true, length = 100) - private String tag; + private List tag=new ArrayList<>(); @Enumerated(EnumType.STRING) @Column @@ -55,11 +55,6 @@ public class Post extends BaseEntity { @Column(nullable = false) private Integer view=0; - @Column(nullable = false) - private Integer scrap=0; /////////////////////////////// - - @Column(nullable = true) - private Timestamp deadline; @Column(nullable = true) private Integer point; @@ -93,15 +88,17 @@ public class Post extends BaseEntity { @OneToMany(mappedBy = "post") private List commentChoiceList = new ArrayList<>(); - @OneToMany(mappedBy = "post") - private List generalQuestionList = new ArrayList<>(); +// @OneToMany(mappedBy = "post") +// private List generalQuestionList = new ArrayList<>(); @OneToMany(mappedBy = "post") - private List gaugeQuestionList = new ArrayList<>(); + private List gaugeQuestionList = new ArrayList<>(); + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "generalPoll_id") + private General_poll generalPoll; + - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) - @JoinColumn(name = "general_vote_id") - private General_vote generalVote; public void setUser(User user){ if(this.user != null) @@ -110,9 +107,23 @@ public void setUser(User user){ user.getPostList().add(this); } - public void setGeneralVote(General_vote generalVote) { - this.generalVote=generalVote; - if(this.generalVote!=null) - generalVote.setPost(this); + public void setParentPost(Post parent){ + if(this.parentPost != null) + parent.getReviewPostList().remove(this); + this.parentPost=parent; + parent.getReviewPostList().add(this); + } + public void setTags(List tags) { + if (tags != null) { + this.tag = new ArrayList<>(tags); + } else { + this.tag.clear(); + } + } + public void setGeneralPoll(General_poll generalPoll) { + this.generalPoll = generalPoll; + if (generalPoll != null && generalPoll.getPost() != this) { + generalPoll.setPost(this); + } } } From dd0f5d697429c63d407db8201db9bce62aef609e Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:38:37 +0900 Subject: [PATCH 066/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=201.=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/enums/PostCategory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/domain/enums/PostCategory.java b/src/main/java/friend/spring/domain/enums/PostCategory.java index 9c2b960..33b20d9 100644 --- a/src/main/java/friend/spring/domain/enums/PostCategory.java +++ b/src/main/java/friend/spring/domain/enums/PostCategory.java @@ -2,5 +2,5 @@ //미정. 그냥 예시. public enum PostCategory { - SPORTS, ANIMALS, FASHION + EDUCATION, ENTERTAINMENT, LIFESTYLE, ECONOMY, SHOPPING, OTHERS } From 8025aa4830f5524e7873005c830f74cae2dd5c16 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:39:11 +0900 Subject: [PATCH 067/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=201.=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=20=20=20=20=202.=20=EA=B8=80=20=EB=93=B1=EB=A1=9D=EC=8B=9C=20P?= =?UTF-8?q?OSTING=EC=83=81=ED=83=9C=EB=A1=9C=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index b653879..c7a9d85 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -1,6 +1,7 @@ package friend.spring.converter; import friend.spring.domain.Post; import friend.spring.domain.enums.PostCategory; +import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; import friend.spring.web.dto.PostRequestDTO; @@ -34,6 +35,8 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { case 3: postType=PostType.REVIEW; break; + default: + break; } if(postType== VOTE) { @@ -44,18 +47,31 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { case 2: postVoteType = PostVoteType.GAUGE; break; + default: + break; } } switch (request.getCategory()){ case 1: - category=PostCategory.SPORTS; + category=PostCategory.EDUCATION; break; case 2: - category=PostCategory.ANIMALS; + category=PostCategory.ENTERTAINMENT; break; case 3: - category=PostCategory.FASHION; + category=PostCategory.LIFESTYLE; + break; + case 4: + category=PostCategory.ECONOMY; + break; + case 5: + category=PostCategory.SHOPPING; + break; + case 6: + category=PostCategory.OTHERS; + break; + default: break; } @@ -66,12 +82,9 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { .postType(postType) .category(category) .voteType(postVoteType) - .file(request.getFile()) - .tag(request.getTag()) - .deadline(request.getDeadline()) .point(request.getPoint()) .view(0) - .scrap(0) + .state(PostState.POSTING) .build(); } } From 988d33c3d38de11f6de5f5de2afb78153ef790c7 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:39:48 +0900 Subject: [PATCH 068/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=201.=20=EB=B6=80?= =?UTF-8?q?=EB=AA=A8=20id=20LONG=ED=83=80=EC=9E=85=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=20=20=20=20=202.=20file=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=20=20=20=20=20=203.=20tag=20list=EB=A1=9C=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/web/dto/PostRequestDTO.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index cebe651..a37f384 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -1,7 +1,10 @@ package friend.spring.web.dto; +import friend.spring.domain.Post; import lombok.Getter; +import org.apache.tomcat.jni.Poll; + import javax.validation.constraints.NotBlank; import java.sql.Timestamp; import java.util.List; @@ -17,11 +20,12 @@ public static class AddPostDTO{ Integer postType; // 1: not vote, 2: vote, 3: review Integer category; //미정 Integer postVoteType;// 1: general, 2: gauge -// Integer parent_id; - List pollOption; - String file; - String tag; + Long parent_id; + List pollOption; + List tag; Timestamp deadline; Integer point; } + + } From 364c73b33d9422986fb4a5644bfac92f33d66238 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:40:25 +0900 Subject: [PATCH 069/255] =?UTF-8?q?=EB=B3=80=EA=B2=BD)=201.=20=EA=B8=80=20?= =?UTF-8?q?=EC=A2=85=EB=A5=98=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95(=EA=B2=8C=EC=9D=B4=EC=A7=80=ED=88=AC=ED=91=9C=20?= =?UTF-8?q?=EB=AF=B8=EC=99=84=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/service/PostServiceImpl.java | 66 ++++++++++++++++--- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index f6f3330..fa75e86 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -1,28 +1,33 @@ package friend.spring.service; -import friend.spring.converter.General_voteConverter; import friend.spring.converter.PostConverter; -import friend.spring.domain.General_vote; +import friend.spring.domain.Candidate; +import friend.spring.domain.General_poll; import friend.spring.domain.Post; import friend.spring.domain.User; -import friend.spring.repository.General_voteRepository; +import friend.spring.domain.enums.PostVoteType; +import friend.spring.repository.CandidateRepository; +import friend.spring.repository.General_PollRepository; import friend.spring.repository.PostRepository; import friend.spring.repository.UserRepository; +import friend.spring.web.dto.PollOptionDTO; import friend.spring.web.dto.PostRequestDTO; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; - -import static friend.spring.domain.enums.PostType.VOTE; +import static friend.spring.domain.enums.PostType.*; +import static friend.spring.domain.enums.PostVoteType.GAUGE; +import static friend.spring.domain.enums.PostVoteType.GENERAL; @Service @RequiredArgsConstructor public class PostServiceImpl implements PostService{ private final PostRepository postRepository; - private final General_voteRepository generalVoteRepository; + private final General_PollRepository generalPollRepository; private final UserRepository userRepository; + private final CandidateRepository candidateRepository; @Override @Transactional @@ -31,13 +36,54 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { User user=userRepository.findById(userId) .orElseThrow(()->new RuntimeException("\""+userId+"\"해당 유저가 없습니다")); newPost.setUser(user); + if(request.getTag()!=null){ + newPost.setTags(request.getTag()); + } + +// if(newPost.getPostType()==NOT_VOTE){ +// +// } - if(newPost.getPostType()==VOTE&&request.getPollOption()!=null){ - General_vote generalVote = General_voteConverter.toGeneralVoteList(request.getPollOption()); - newPost.setGeneralVote(generalVote); + if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL&&request.getPollOption()!=null){ + General_poll generalPoll = General_poll.builder() + .deadline(request.getDeadline()) + .build(); + newPost.setGeneralPoll(generalPoll); + generalPollRepository.save(generalPoll); - generalVoteRepository.save(generalVote); + for (PollOptionDTO option : request.getPollOption()) { + Candidate candidate = Candidate.builder() + .name(option.getOptionString()) + .image(option.getOptionImg()) + .build(); + + candidate.setGeneralPoll(generalPoll); + candidateRepository.save(candidate); + } + } + + if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GAUGE&&request.getPollOption()!=null){ + General_poll generalPoll = General_poll.builder() + .deadline(request.getDeadline()) + .build(); + newPost.setGeneralPoll(generalPoll); + generalPollRepository.save(generalPoll); + + for (PollOptionDTO option : request.getPollOption()) { + Candidate candidate = Candidate.builder() + .name(option.getOptionString()) + .image(option.getOptionImg()) + .build(); + + candidate.setGeneralPoll(generalPoll); + candidateRepository.save(candidate); + } + } + if(newPost.getPostType()==REVIEW&&request.getParent_id()!=null){ + Post parent=postRepository.findById(request.getParent_id()) + .orElseThrow(()->new RuntimeException("\""+request.getParent_id()+"\"해당 글이 없습니다")); + newPost.setParentPost(parent); } return postRepository.save(newPost); From f48b64df76d2677c0bd368ef501ebe503ef493f5 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:40:40 +0900 Subject: [PATCH 070/255] =?UTF-8?q?=EC=B6=94=EA=B0=80)=201.=20=ED=88=AC?= =?UTF-8?q?=ED=91=9C=20=ED=9B=84=EB=B3=B4=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/domain/Candidate.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/main/java/friend/spring/domain/Candidate.java diff --git a/src/main/java/friend/spring/domain/Candidate.java b/src/main/java/friend/spring/domain/Candidate.java new file mode 100644 index 0000000..338b1b7 --- /dev/null +++ b/src/main/java/friend/spring/domain/Candidate.java @@ -0,0 +1,50 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import lombok.*; +import org.hibernate.Hibernate; + +import javax.persistence.*; +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Candidate extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + private String image; + +// @ManyToOne(fetch = FetchType.LAZY) +// @JoinColumn(name = "generalPoll_id") +// private General_poll generalPoll; + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "generalPoll_id") + private General_poll generalPoll; + + + +// public void setGeneralPoll(General_poll generalPoll){ +// this.generalPoll = generalPoll; +// if (generalPoll != null) { +// generalPoll.getCandidateList().add(this); +// } +// +// } + public void setGeneralPoll(General_poll generalPoll) { + this.generalPoll = generalPoll; + if (this.generalPoll != null) { + Hibernate.initialize(this.generalPoll); + if (this.generalPoll.getCandidateList() != null) { + this.generalPoll.getCandidateList().add(this); + } + } +} + + +} From 9756d46e5a970cf7524a3691d272d40bfd5a7025 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:40:48 +0900 Subject: [PATCH 071/255] =?UTF-8?q?=EC=B6=94=EA=B0=80)=201.=20=ED=88=AC?= =?UTF-8?q?=ED=91=9C=20=ED=9B=84=EB=B3=B4=20repository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/repository/CandidateRepository.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/friend/spring/repository/CandidateRepository.java diff --git a/src/main/java/friend/spring/repository/CandidateRepository.java b/src/main/java/friend/spring/repository/CandidateRepository.java new file mode 100644 index 0000000..d04ffa3 --- /dev/null +++ b/src/main/java/friend/spring/repository/CandidateRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.Candidate; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CandidateRepository extends JpaRepository { +} From ee6073bfbac3a330d9c414c0988d56b568d965b2 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 29 Jan 2024 23:41:17 +0900 Subject: [PATCH 072/255] =?UTF-8?q?=EC=B6=94=EA=B0=80)=201.=20=ED=88=AC?= =?UTF-8?q?=ED=91=9C=20=ED=9B=84=EB=B3=B4=20(=EA=B8=80,=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=EB=A7=81=ED=81=AC)=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=EB=B0=9B=EA=B8=B0=20=EC=9C=84=ED=95=9C=20DTO=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/web/dto/PollOptionDTO.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/friend/spring/web/dto/PollOptionDTO.java diff --git a/src/main/java/friend/spring/web/dto/PollOptionDTO.java b/src/main/java/friend/spring/web/dto/PollOptionDTO.java new file mode 100644 index 0000000..bceb000 --- /dev/null +++ b/src/main/java/friend/spring/web/dto/PollOptionDTO.java @@ -0,0 +1,9 @@ +package friend.spring.web.dto; + +import lombok.Getter; + +@Getter +public class PollOptionDTO { + private String optionString; + private String optionImg; +} From 3b925fe7d3ee745182ebd3eb39843fb428ccf0ae Mon Sep 17 00:00:00 2001 From: hjh Date: Tue, 30 Jan 2024 16:40:00 +0900 Subject: [PATCH 073/255] =?UTF-8?q?#2=20Feat:card=ED=83=80=EC=9E=85,=20gua?= =?UTF-8?q?ge=ED=83=80=EC=9E=85=20=EC=B6=94=EA=B0=80(aws=EC=9E=84=EC=8B=9C?= =?UTF-8?q?=20=EC=A3=BC=EC=84=9D=EC=B2=98=EB=A6=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 18 +-- .../friend/spring/aws/s3/AmazonS3Manager.java | 122 ++++++++--------- .../friend/spring/config/AmazonConfig.java | 124 +++++++++--------- .../java/friend/spring/config/S3Config.java | 30 ++--- ...verter.java => General_PollConverter.java} | 3 +- .../spring/converter/PostConverter.java | 3 + .../java/friend/spring/domain/Candidate.java | 24 ++-- .../java/friend/spring/domain/Gauge_poll.java | 18 ++- src/main/java/friend/spring/domain/Post.java | 23 +++- .../spring/domain/enums/PostVoteType.java | 2 +- .../spring/service/PostServiceImpl.java | 41 +++--- .../java/friend/spring/service/S3Service.java | 58 ++++---- .../web/controller/PostRestController.java | 4 + .../spring/web/controller/S3Controller.java | 42 +++--- src/main/resources/application.yml | 29 +--- 15 files changed, 283 insertions(+), 258 deletions(-) rename src/main/java/friend/spring/converter/{General_voteConverter.java => General_PollConverter.java} (80%) diff --git a/build.gradle b/build.gradle index a5d4470..6360e44 100644 --- a/build.gradle +++ b/build.gradle @@ -33,15 +33,15 @@ dependencies { implementation 'io.springfox:springfox-swagger-ui:2.9.2' //jwt - testImplementation 'org.springframework.security:spring-security-test' - implementation 'io.jsonwebtoken:jjwt-api:0.12.3' - implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' - implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' - - // S3 - implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' - implementation platform('software.amazon.awssdk:bom:2.20.56') - implementation 'software.amazon.awssdk:s3' +// testImplementation 'org.springframework.security:spring-security-test' +// implementation 'io.jsonwebtoken:jjwt-api:0.12.3' +// implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' +// implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' +// +// // S3 +// implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' +// implementation platform('software.amazon.awssdk:bom:2.20.56') +// implementation 'software.amazon.awssdk:s3' } tasks.named('test') { diff --git a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java index 1c32fe3..5982231 100644 --- a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java +++ b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java @@ -1,61 +1,61 @@ -package friend.spring.aws.s3; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.ObjectMetadata; -import friend.spring.config.AmazonConfig; -import friend.spring.domain.Uuid; -import friend.spring.repository.UuidRepository; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.web.multipart.MultipartFile; -import software.amazon.awssdk.core.sync.RequestBody; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; - -import java.io.IOException; - -@Slf4j -@Component -@RequiredArgsConstructor -public class AmazonS3Manager{ - - private final AmazonS3 amazonS3; - - private final S3Client s3Client; - - private final AmazonConfig amazonConfig; - - private final UuidRepository uuidRepository; - - public String uploadFile(String keyName, MultipartFile file){ - ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentLength(file.getSize()); - try { - PutObjectRequest putObjectRequest = PutObjectRequest.builder() - .bucket(amazonConfig.getBucket()) - .key(keyName) - .contentType(file.getContentType()) - .contentDisposition("inline") - .build(); - s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(file.getInputStream(), file.getSize())); - - }catch (IOException e){ - log.error("error at AmazonS3Manager uploadFile : {}", (Object) e.getStackTrace()); - } - - return amazonS3.getUrl(amazonConfig.getBucket(), keyName).toString(); - } - - public String generateUserKeyName(Uuid uuid) { - return amazonConfig.getUserPath() + '/' + uuid.getUuid(); - } - - public String generatePostKeyName(Uuid uuid) { - return amazonConfig.getPostPath() + '/' + uuid.getUuid(); - } - - public String generateReportKeyName(Uuid uuid) { - return amazonConfig.getReportPath() + '/' + uuid.getUuid(); - } -} \ No newline at end of file +//package friend.spring.aws.s3; +// +//import com.amazonaws.services.s3.AmazonS3; +//import com.amazonaws.services.s3.model.ObjectMetadata; +//import friend.spring.config.AmazonConfig; +//import friend.spring.domain.Uuid; +//import friend.spring.repository.UuidRepository; +//import lombok.RequiredArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.stereotype.Component; +//import org.springframework.web.multipart.MultipartFile; +//import software.amazon.awssdk.core.sync.RequestBody; +//import software.amazon.awssdk.services.s3.S3Client; +//import software.amazon.awssdk.services.s3.model.PutObjectRequest; +// +//import java.io.IOException; +// +//@Slf4j +//@Component +//@RequiredArgsConstructor +//public class AmazonS3Manager{ +// +// private final AmazonS3 amazonS3; +// +// private final S3Client s3Client; +// +// private final AmazonConfig amazonConfig; +// +// private final UuidRepository uuidRepository; +// +// public String uploadFile(String keyName, MultipartFile file){ +// ObjectMetadata metadata = new ObjectMetadata(); +// metadata.setContentLength(file.getSize()); +// try { +// PutObjectRequest putObjectRequest = PutObjectRequest.builder() +// .bucket(amazonConfig.getBucket()) +// .key(keyName) +// .contentType(file.getContentType()) +// .contentDisposition("inline") +// .build(); +// s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(file.getInputStream(), file.getSize())); +// +// }catch (IOException e){ +// log.error("error at AmazonS3Manager uploadFile : {}", (Object) e.getStackTrace()); +// } +// +// return amazonS3.getUrl(amazonConfig.getBucket(), keyName).toString(); +// } +// +// public String generateUserKeyName(Uuid uuid) { +// return amazonConfig.getUserPath() + '/' + uuid.getUuid(); +// } +// +// public String generatePostKeyName(Uuid uuid) { +// return amazonConfig.getPostPath() + '/' + uuid.getUuid(); +// } +// +// public String generateReportKeyName(Uuid uuid) { +// return amazonConfig.getReportPath() + '/' + uuid.getUuid(); +// } +//} \ No newline at end of file diff --git a/src/main/java/friend/spring/config/AmazonConfig.java b/src/main/java/friend/spring/config/AmazonConfig.java index a0597eb..aaca940 100644 --- a/src/main/java/friend/spring/config/AmazonConfig.java +++ b/src/main/java/friend/spring/config/AmazonConfig.java @@ -1,62 +1,62 @@ -package friend.spring.config; - -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSCredentialsProvider; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import lombok.Getter; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.annotation.PostConstruct; - -@Configuration -@Getter -public class AmazonConfig { - - - private AWSCredentials awsCredentials; - - @Value("${cloud.aws.credentials.accessKey}") - private String accessKey; - - @Value("${cloud.aws.credentials.secretKey}") - private String secretKey; - - @Value("${cloud.aws.region.static}") - private String region; - - @Value("${cloud.aws.s3.bucket}") - private String bucket; - - @Value("${cloud.aws.s3.path.user}") - private String userPath; - - @Value("${cloud.aws.s3.path.post}") - private String postPath; - - @Value("${cloud.aws.s3.path.report}") - private String reportPath; - - @PostConstruct - public void init() { - this.awsCredentials = new BasicAWSCredentials(accessKey, secretKey); - } - - @Bean - public AmazonS3 amazonS3() { - AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); - return AmazonS3ClientBuilder.standard() - .withRegion(region) - .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) - .build(); - } - - @Bean - public AWSCredentialsProvider awsCredentialsProvider() { - return new AWSStaticCredentialsProvider(awsCredentials); - } -} \ No newline at end of file +//package friend.spring.config; +// +//import com.amazonaws.auth.AWSCredentials; +//import com.amazonaws.auth.AWSCredentialsProvider; +//import com.amazonaws.auth.AWSStaticCredentialsProvider; +//import com.amazonaws.auth.BasicAWSCredentials; +//import com.amazonaws.services.s3.AmazonS3; +//import com.amazonaws.services.s3.AmazonS3ClientBuilder; +//import lombok.Getter; +//import org.springframework.beans.factory.annotation.Value; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +// +//import javax.annotation.PostConstruct; +// +//@Configuration +//@Getter +//public class AmazonConfig { +// +// +// private AWSCredentials awsCredentials; +// +// @Value("${cloud.aws.credentials.accessKey}") +// private String accessKey; +// +// @Value("${cloud.aws.credentials.secretKey}") +// private String secretKey; +// +// @Value("${cloud.aws.region.static}") +// private String region; +// +// @Value("${cloud.aws.s3.bucket}") +// private String bucket; +// +// @Value("${cloud.aws.s3.path.user}") +// private String userPath; +// +// @Value("${cloud.aws.s3.path.post}") +// private String postPath; +// +// @Value("${cloud.aws.s3.path.report}") +// private String reportPath; +// +// @PostConstruct +// public void init() { +// this.awsCredentials = new BasicAWSCredentials(accessKey, secretKey); +// } +// +// @Bean +// public AmazonS3 amazonS3() { +// AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); +// return AmazonS3ClientBuilder.standard() +// .withRegion(region) +// .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) +// .build(); +// } +// +// @Bean +// public AWSCredentialsProvider awsCredentialsProvider() { +// return new AWSStaticCredentialsProvider(awsCredentials); +// } +//} \ No newline at end of file diff --git a/src/main/java/friend/spring/config/S3Config.java b/src/main/java/friend/spring/config/S3Config.java index 466cced..91adf45 100644 --- a/src/main/java/friend/spring/config/S3Config.java +++ b/src/main/java/friend/spring/config/S3Config.java @@ -1,15 +1,15 @@ -package friend.spring.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.s3.S3Client; - -@Configuration -public class S3Config { - - @Bean - public S3Client defaultS3Client() { - return S3Client.builder().region(Region.AP_NORTHEAST_2).build(); - } -} +//package friend.spring.config; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import software.amazon.awssdk.regions.Region; +//import software.amazon.awssdk.services.s3.S3Client; +// +//@Configuration +//public class S3Config { +// +// @Bean +// public S3Client defaultS3Client() { +// return S3Client.builder().region(Region.AP_NORTHEAST_2).build(); +// } +//} diff --git a/src/main/java/friend/spring/converter/General_voteConverter.java b/src/main/java/friend/spring/converter/General_PollConverter.java similarity index 80% rename from src/main/java/friend/spring/converter/General_voteConverter.java rename to src/main/java/friend/spring/converter/General_PollConverter.java index b7e2fc3..7f38570 100644 --- a/src/main/java/friend/spring/converter/General_voteConverter.java +++ b/src/main/java/friend/spring/converter/General_PollConverter.java @@ -2,11 +2,10 @@ import friend.spring.domain.Candidate; import friend.spring.domain.General_poll; -import friend.spring.web.dto.PollOptionDTO; import java.util.List; -public class General_voteConverter { +public class General_PollConverter { public static General_poll toGeneralVoteList(List pollOptions) { return General_poll.builder() diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index c7a9d85..7f65647 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -47,6 +47,9 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { case 2: postVoteType = PostVoteType.GAUGE; break; + case 3: + postVoteType = PostVoteType.CARD; + break; default: break; } diff --git a/src/main/java/friend/spring/domain/Candidate.java b/src/main/java/friend/spring/domain/Candidate.java index 338b1b7..8617efb 100644 --- a/src/main/java/friend/spring/domain/Candidate.java +++ b/src/main/java/friend/spring/domain/Candidate.java @@ -20,22 +20,14 @@ public class Candidate extends BaseEntity { private String image; -// @ManyToOne(fetch = FetchType.LAZY) -// @JoinColumn(name = "generalPoll_id") -// private General_poll generalPoll; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "generalPoll_id") private General_poll generalPoll; + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "cardPoll_id") + private Card_poll cardPoll; - -// public void setGeneralPoll(General_poll generalPoll){ -// this.generalPoll = generalPoll; -// if (generalPoll != null) { -// generalPoll.getCandidateList().add(this); -// } -// -// } public void setGeneralPoll(General_poll generalPoll) { this.generalPoll = generalPoll; if (this.generalPoll != null) { @@ -46,5 +38,15 @@ public void setGeneralPoll(General_poll generalPoll) { } } + public void setCardPoll(Card_poll cardPoll) { + this.cardPoll = cardPoll; + if (this.cardPoll != null) { + Hibernate.initialize(this.cardPoll); + if (this.cardPoll.getCandidateList() != null) { + this.cardPoll.getCandidateList().add(this); + } + } + } + } diff --git a/src/main/java/friend/spring/domain/Gauge_poll.java b/src/main/java/friend/spring/domain/Gauge_poll.java index f9220f2..53c00d5 100644 --- a/src/main/java/friend/spring/domain/Gauge_poll.java +++ b/src/main/java/friend/spring/domain/Gauge_poll.java @@ -4,6 +4,8 @@ import lombok.*; import javax.persistence.*; +import java.sql.Timestamp; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -18,16 +20,26 @@ public class Gauge_poll extends BaseEntity { private Long id; @Column(nullable = false) - private Integer min; + private Integer min=0; @Column(nullable = false) - private Integer max; + private Integer max=100; - @ManyToOne(fetch = FetchType.LAZY) + @Column(nullable = false) + private Integer value=0; + + @Column(nullable = true) + private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. + + @OneToOne(mappedBy = "gaugePoll", cascade = CascadeType.ALL) @JoinColumn(name = "post_id") private Post post; @Builder.Default @OneToMany(mappedBy = "gaugeQuestion") private List gaugeVoteList = new ArrayList<>(); + + public void setPost(Post post) { + this.post = post; + } } diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 3be1d34..8232247 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -91,8 +91,13 @@ public class Post extends BaseEntity { // @OneToMany(mappedBy = "post") // private List generalQuestionList = new ArrayList<>(); - @OneToMany(mappedBy = "post") - private List gaugeQuestionList = new ArrayList<>(); + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "cardPoll_id") + private Card_poll cardPoll; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name="gaugePoll_id") + private Gauge_poll gaugePoll; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "generalPoll_id") @@ -126,4 +131,18 @@ public void setGeneralPoll(General_poll generalPoll) { generalPoll.setPost(this); } } + + public void setGaugePoll(Gauge_poll gaugePoll) { + this.gaugePoll = gaugePoll; + if (gaugePoll != null && gaugePoll.getPost() != this) { + gaugePoll.setPost(this); + } + } + + public void setCardPoll(Card_poll cardPoll) { + this.cardPoll = cardPoll; + if (cardPoll != null && cardPoll.getPost() != this) { + cardPoll.setPost(this); + } + } } diff --git a/src/main/java/friend/spring/domain/enums/PostVoteType.java b/src/main/java/friend/spring/domain/enums/PostVoteType.java index d1cd6a4..c9b43b4 100644 --- a/src/main/java/friend/spring/domain/enums/PostVoteType.java +++ b/src/main/java/friend/spring/domain/enums/PostVoteType.java @@ -1,5 +1,5 @@ package friend.spring.domain.enums; public enum PostVoteType { - GENERAL, GAUGE + GENERAL, GAUGE, CARD } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 6ebcd83..0cf0066 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -1,15 +1,11 @@ package friend.spring.service; +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.apiPayload.handler.UserHandler; import friend.spring.converter.PostConverter; -import friend.spring.domain.Candidate; -import friend.spring.domain.General_poll; -import friend.spring.domain.Post; -import friend.spring.domain.User; +import friend.spring.domain.*; import friend.spring.domain.enums.PostVoteType; -import friend.spring.repository.CandidateRepository; -import friend.spring.repository.General_PollRepository; -import friend.spring.repository.PostRepository; -import friend.spring.repository.UserRepository; +import friend.spring.repository.*; import friend.spring.web.dto.PollOptionDTO; import friend.spring.web.dto.PostRequestDTO; import lombok.RequiredArgsConstructor; @@ -17,9 +13,7 @@ import org.springframework.transaction.annotation.Transactional; import static friend.spring.domain.enums.PostType.*; -import static friend.spring.domain.enums.PostVoteType.GAUGE; -import static friend.spring.domain.enums.PostVoteType.GENERAL; - +import static friend.spring.domain.enums.PostVoteType.*; @Service @@ -30,7 +24,8 @@ public class PostServiceImpl implements PostService{ private final General_PollRepository generalPollRepository; private final UserRepository userRepository; private final CandidateRepository candidateRepository; - + private final Gauge_PollRepository gaugePollRepository; + private final Card_PollRepository cardPollRepository; @Override public void checkPost(Boolean flag) { if (!flag) { @@ -73,12 +68,12 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { } } - if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GAUGE&&request.getPollOption()!=null){ - General_poll generalPoll = General_poll.builder() + if(newPost.getPostType()==VOTE&&newPost.getVoteType()==CARD&&request.getPollOption()!=null){ + Card_poll cardPoll = Card_poll.builder() .deadline(request.getDeadline()) .build(); - newPost.setGeneralPoll(generalPoll); - generalPollRepository.save(generalPoll); + newPost.setCardPoll(cardPoll); + cardPollRepository.save(cardPoll); for (PollOptionDTO option : request.getPollOption()) { Candidate candidate = Candidate.builder() @@ -86,11 +81,23 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { .image(option.getOptionImg()) .build(); - candidate.setGeneralPoll(generalPoll); + candidate.setCardPoll(cardPoll); candidateRepository.save(candidate); } } + if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GAUGE&&request.getPollOption()!=null){ + Gauge_poll gaugePoll = Gauge_poll.builder() + .max(100) + .min(0) + .value(0) + .deadline(request.getDeadline()) + .build(); + + newPost.setGaugePoll(gaugePoll); + gaugePollRepository.save(gaugePoll); + } + if(newPost.getPostType()==REVIEW&&request.getParent_id()!=null){ Post parent=postRepository.findById(request.getParent_id()) .orElseThrow(()->new RuntimeException("\""+request.getParent_id()+"\"해당 글이 없습니다")); diff --git a/src/main/java/friend/spring/service/S3Service.java b/src/main/java/friend/spring/service/S3Service.java index 2c34a8f..6c6e26b 100644 --- a/src/main/java/friend/spring/service/S3Service.java +++ b/src/main/java/friend/spring/service/S3Service.java @@ -1,29 +1,29 @@ -package friend.spring.service; - -import friend.spring.aws.s3.AmazonS3Manager; -import friend.spring.domain.Uuid; -import friend.spring.repository.UuidRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import java.util.UUID; - -@Service -@Transactional -@RequiredArgsConstructor -public class S3Service { - private final UuidRepository uuidRepository; - private final AmazonS3Manager s3Manager; - - // 유저 프로필 사진 올리기인 경우 - public String uploadUserImage(MultipartFile file) { - String uuid = UUID.randomUUID().toString(); - Uuid savedUuid = uuidRepository.save(Uuid.builder() - .uuid(uuid).build()); - - String pictureUrl = s3Manager.uploadFile(s3Manager.generateUserKeyName(savedUuid), file); - return pictureUrl; - } -} +//package friend.spring.service; +// +//import friend.spring.aws.s3.AmazonS3Manager; +//import friend.spring.domain.Uuid; +//import friend.spring.repository.UuidRepository; +//import lombok.RequiredArgsConstructor; +//import org.springframework.stereotype.Service; +//import org.springframework.transaction.annotation.Transactional; +//import org.springframework.web.multipart.MultipartFile; +// +//import java.util.UUID; +// +//@Service +//@Transactional +//@RequiredArgsConstructor +//public class S3Service { +// private final UuidRepository uuidRepository; +// private final AmazonS3Manager s3Manager; +// +// // 유저 프로필 사진 올리기인 경우 +// public String uploadUserImage(MultipartFile file) { +// String uuid = UUID.randomUUID().toString(); +// Uuid savedUuid = uuidRepository.save(Uuid.builder() +// .uuid(uuid).build()); +// +// String pictureUrl = s3Manager.uploadFile(s3Manager.generateUserKeyName(savedUuid), file); +// return pictureUrl; +// } +//} diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index c543e98..74907c8 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -5,6 +5,7 @@ import friend.spring.service.PostService; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; +import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -17,6 +18,9 @@ public class PostRestController { private final PostService postService; @PostMapping("/{user-id}") + @Operation(summary = "글 작성 API", description = "PostType = 1 : NOT_VOTE, 2 : VOTE, 3 : REVIEW
" + + "Category = 1 : EDUCATION, 2 : ENTERTAINMENT, 3 : LIFESTYLE, 4 : ECONOMY, 5 : SHOPPING, 6 : OTHERS
" + + "postVoteType = 1 : GENERAL, 2 : GAUGE") public ApiResponse join(@RequestBody @Valid PostRequestDTO.AddPostDTO request, @PathVariable(name="user-id")Long UserId){ Post post= postService.joinPost(request,UserId); diff --git a/src/main/java/friend/spring/web/controller/S3Controller.java b/src/main/java/friend/spring/web/controller/S3Controller.java index 8052453..478d475 100644 --- a/src/main/java/friend/spring/web/controller/S3Controller.java +++ b/src/main/java/friend/spring/web/controller/S3Controller.java @@ -1,21 +1,21 @@ -package friend.spring.web.controller; - -import friend.spring.apiPayload.ApiResponse; -import friend.spring.service.S3Service; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/uploadImage") -public class S3Controller { - private final S3Service s3Service; - - // 유저 이미지 올리기 - @PostMapping(value = "", consumes = "multipart/form-data") - public ApiResponse uploadUserImage(@RequestParam("file") MultipartFile file) { - String url = s3Service.uploadUserImage(file); - return ApiResponse.onSuccess(url); - } -} +//package friend.spring.web.controller; +// +//import friend.spring.apiPayload.ApiResponse; +//import friend.spring.service.S3Service; +//import lombok.RequiredArgsConstructor; +//import org.springframework.web.bind.annotation.*; +//import org.springframework.web.multipart.MultipartFile; +// +//@RestController +//@RequiredArgsConstructor +//@RequestMapping("/uploadImage") +//public class S3Controller { +// private final S3Service s3Service; +// +// // 유저 이미지 올리기 +// @PostMapping(value = "", consumes = "multipart/form-data") +// public ApiResponse uploadUserImage(@RequestParam("file") MultipartFile file) { +// String url = s3Service.uploadUserImage(file); +// return ApiResponse.onSuccess(url); +// } +//} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a059c0f..fc07363 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,8 +1,8 @@ spring: datasource: - url: ${aws.db.url} - username: ${aws.db.username} - password: ${aws.db.password} + url: jdbc:mysql://localhost:3306/gomin + username: root + password: 1234 driver-class-name: com.mysql.cj.jdbc.Driver sql: init: @@ -17,25 +17,4 @@ spring: hbm2ddl: auto: update default_batch_fetch_size: 1000 - globally_quoted_identifiers: true -cloud: - aws: - s3: - bucket: solution-friend-bucket - path: - user: users - post: posts - report: reports - region: - static: ap-northeast-2 - stack: - auto: false - credentials: - accessKey: ${AWS_ACCESS_KEY_ID} - secretKey: ${AWS_SECRET_ACCESS_KEY} -logging: - level: - com: - amazonaws: - util: - EC2MetadataUtils: error \ No newline at end of file + globally_quoted_identifiers: true \ No newline at end of file From 6efeb8220b6a59bfad0bad2beb2dee55b99b260c Mon Sep 17 00:00:00 2001 From: hjh Date: Tue, 30 Jan 2024 16:40:21 +0900 Subject: [PATCH 074/255] =?UTF-8?q?#2=20Feat:card=ED=83=80=EC=9E=85,=20gua?= =?UTF-8?q?ge=ED=83=80=EC=9E=85=20=EC=B6=94=EA=B0=80(aws=EC=9E=84=EC=8B=9C?= =?UTF-8?q?=20=EC=A3=BC=EC=84=9D=EC=B2=98=EB=A6=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/domain/Card_poll.java | 40 +++++++++++++++++++ .../java/friend/spring/domain/Card_vote.java | 23 +++++++++++ .../repository/Card_PollRepository.java | 7 ++++ .../repository/Gauge_PollRepository.java | 7 ++++ 4 files changed, 77 insertions(+) create mode 100644 src/main/java/friend/spring/domain/Card_poll.java create mode 100644 src/main/java/friend/spring/domain/Card_vote.java create mode 100644 src/main/java/friend/spring/repository/Card_PollRepository.java create mode 100644 src/main/java/friend/spring/repository/Gauge_PollRepository.java diff --git a/src/main/java/friend/spring/domain/Card_poll.java b/src/main/java/friend/spring/domain/Card_poll.java new file mode 100644 index 0000000..a490fca --- /dev/null +++ b/src/main/java/friend/spring/domain/Card_poll.java @@ -0,0 +1,40 @@ +package friend.spring.domain; + +import lombok.*; + +import javax.persistence.*; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Card_poll { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = true) + private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "card_vote_id") + private Card_vote cardVote; + + @OneToOne(mappedBy = "cardPoll", cascade = CascadeType.ALL) + private Post post; + + @OneToMany(mappedBy = "cardPoll",cascade = CascadeType.ALL) + private List candidateList=new ArrayList<>(); + + public void setPost(Post post) { + this.post = post; + } +} diff --git a/src/main/java/friend/spring/domain/Card_vote.java b/src/main/java/friend/spring/domain/Card_vote.java new file mode 100644 index 0000000..9f88bc4 --- /dev/null +++ b/src/main/java/friend/spring/domain/Card_vote.java @@ -0,0 +1,23 @@ +package friend.spring.domain; + +import lombok.*; + +import javax.persistence.*; +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Card_vote { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "cardPoll_id") + private Card_poll cardPoll; +} diff --git a/src/main/java/friend/spring/repository/Card_PollRepository.java b/src/main/java/friend/spring/repository/Card_PollRepository.java new file mode 100644 index 0000000..9b39eb8 --- /dev/null +++ b/src/main/java/friend/spring/repository/Card_PollRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.Card_poll; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface Card_PollRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/repository/Gauge_PollRepository.java b/src/main/java/friend/spring/repository/Gauge_PollRepository.java new file mode 100644 index 0000000..bda947d --- /dev/null +++ b/src/main/java/friend/spring/repository/Gauge_PollRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.Gauge_poll; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface Gauge_PollRepository extends JpaRepository { +} From aa4c4bf58b084669fc4612a4ba76657cb3035632 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Wed, 31 Jan 2024 12:00:12 +0900 Subject: [PATCH 075/255] =?UTF-8?q?#32=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20&=20CommentHandler=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 3 +- .../apiPayload/handler/CommentHandler.java | 10 ++++++ .../java/friend/spring/domain/Comment.java | 4 +++ .../friend/spring/service/CommentService.java | 4 +++ .../spring/service/CommentServiceImpl.java | 33 +++++++++++++++---- .../spring/service/PostServiceImpl.java | 6 ++-- .../web/controller/CommentRestController.java | 23 +++++++++++++ .../spring/web/dto/CommentRequestDTO.java | 9 +++++ 8 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 src/main/java/friend/spring/apiPayload/handler/CommentHandler.java diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index dd1672d..a832627 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -21,13 +21,14 @@ public enum ErrorStatus implements BaseErrorCode { // 글 관련 응답 POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "글을 찾을 수 없습니다."), - NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "POST4002", "올바른 사용자(글 작성자)가 아닙니다."), + POST_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "POST4002", "올바른 사용자(글 작성자)가 아닙니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), COMMENT_LIKE_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4002", "댓글에 대한 좋아요 데이터를 찾을 수 없습니다."), COMMENT_CHOICE_OVER_ONE(HttpStatus.BAD_REQUEST, "COMMENT4003", "댓글 채택은 1개 댓글에 대해서만 가능합니다."), COMMENT_SELECT_MYSELF(HttpStatus.BAD_REQUEST, "COMMENT4004", "자기 자신은 채택할 수 없습니다."), + COMMENT_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "COMMENT4005", "올바른 사용자(댓글 작성자)가 아닙니다."), ; diff --git a/src/main/java/friend/spring/apiPayload/handler/CommentHandler.java b/src/main/java/friend/spring/apiPayload/handler/CommentHandler.java new file mode 100644 index 0000000..f12198b --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/handler/CommentHandler.java @@ -0,0 +1,10 @@ +package friend.spring.apiPayload.handler; + +import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.code.BaseErrorCode; + +public class CommentHandler extends GeneralException { + public CommentHandler(BaseErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/friend/spring/domain/Comment.java b/src/main/java/friend/spring/domain/Comment.java index 1085df8..109b062 100644 --- a/src/main/java/friend/spring/domain/Comment.java +++ b/src/main/java/friend/spring/domain/Comment.java @@ -47,4 +47,8 @@ public class Comment extends BaseEntity { @Builder.Default @OneToMany(mappedBy = "comment") private List commentLikeList = new ArrayList<>(); + + public void update(String content) { + this.content = content; + } } diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index fc0d98f..1fc6008 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -14,6 +14,8 @@ public interface CommentService { void checkCommentLike(Boolean flag); void checkCommentChoice(Boolean flag); void checkSelectCommentAnotherUser(Boolean flag); + + void checkCommentWriterUser(Boolean flag); public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId); Comment_like likeComment(Long postId, Long commentId, Long userId); @@ -23,4 +25,6 @@ public interface CommentService { void dislikeComment(Long postId, Long commentId, Long userId); Comment_choice selectComment(Long postId, Long commentId, Long userId); + + void editComment(Long postId, Long commentId, CommentRequestDTO.commentEditReq request, Long userId); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index d798d47..c60e087 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -1,7 +1,8 @@ package friend.spring.service; +import friend.spring.apiPayload.GeneralException; import friend.spring.apiPayload.code.status.ErrorStatus; -import friend.spring.apiPayload.handler.UserHandler; +import friend.spring.apiPayload.handler.CommentHandler; import friend.spring.converter.CommentConverter; import friend.spring.domain.Comment; import friend.spring.domain.Post; @@ -38,32 +39,40 @@ public class CommentServiceImpl implements CommentService { @Override public void checkComment(Boolean flag) { if (!flag) { - throw new UserHandler(ErrorStatus.COMMENT_NOT_FOUND); + throw new CommentHandler(ErrorStatus.COMMENT_NOT_FOUND); } } @Override public void checkCommentLike(Boolean flag) { if (!flag) { - throw new UserHandler(ErrorStatus.COMMENT_LIKE_NOT_FOUND); + throw new CommentHandler(ErrorStatus.COMMENT_LIKE_NOT_FOUND); } } @Override public void checkCommentChoice(Boolean flag) { if (!flag) { - throw new UserHandler(ErrorStatus.COMMENT_CHOICE_OVER_ONE); + throw new CommentHandler(ErrorStatus.COMMENT_CHOICE_OVER_ONE); } } @Override public void checkSelectCommentAnotherUser(Boolean flag) { if (!flag) { - throw new UserHandler(ErrorStatus.COMMENT_SELECT_MYSELF); + throw new CommentHandler(ErrorStatus.COMMENT_SELECT_MYSELF); } } @Override + public void checkCommentWriterUser(Boolean flag) { + if (!flag) { + throw new CommentHandler(ErrorStatus.COMMENT_NOT_CORRECT_USER); + } + } + + @Override + @Transactional public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId) { Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { @@ -208,5 +217,17 @@ public Comment_choice selectComment(Long postId, Long commentId, Long userId) { return commentChoiceRepository.save(comment_choice); } - + @Override + @Transactional + public void editComment(Long postId, Long commentId, CommentRequestDTO.commentEditReq request, Long userId) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + Comment comment = commentRepository.findById(commentId).orElseThrow(() -> new GeneralException(ErrorStatus.COMMENT_NOT_FOUND)); + // 로그인한 사용자가 이 댓글의 작성자인지 확인 + if (!Objects.equals(user.getId(), comment.getUser().getId())) { + // 작성자가 아닌 경우 -> 에러 반환 + this.checkCommentWriterUser(false); + } + comment.update(request.getContent()); + } } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 9cc052b..108256e 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -1,7 +1,7 @@ package friend.spring.service; import friend.spring.apiPayload.code.status.ErrorStatus; -import friend.spring.apiPayload.handler.UserHandler; +import friend.spring.apiPayload.handler.PostHandler; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -11,14 +11,14 @@ public class PostServiceImpl implements PostService { @Override public void checkPost(Boolean flag) { if (!flag) { - throw new UserHandler(ErrorStatus.POST_NOT_FOUND); + throw new PostHandler(ErrorStatus.POST_NOT_FOUND); } } @Override public void checkPostWriterUser(Boolean flag) { if (!flag) { - throw new UserHandler(ErrorStatus.NOT_CORRECT_USER); + throw new PostHandler(ErrorStatus.POST_NOT_CORRECT_USER); } } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 945556c..3bc05bf 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -143,4 +143,27 @@ public ApiResponse selectComment( Comment_choice comment_choice = commentService.selectComment(postId, commentId, userId); return ApiResponse.onSuccess(CommentConverter.toCommentSelectRes(comment_choice)); } + + // 댓글 수정 + @PostMapping("/{post-id}/comment/{comment-id}/edit") + @Operation(summary = "댓글 수정 API", description = "댓글 수정하는 API입니다. ex) /posts/1/comment/1/edit") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "comment-id", description = "path variable - 댓글 아이디"), + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + }) + public ApiResponse editComment( + @PathVariable("post-id") Long postId, + @PathVariable("comment-id") Long commentId, + @RequestBody CommentRequestDTO.commentEditReq request, + @RequestHeader("userId") Long userId + ) { + commentService.editComment(postId, commentId, request, userId); + return ApiResponse.onSuccess(null); + } } diff --git a/src/main/java/friend/spring/web/dto/CommentRequestDTO.java b/src/main/java/friend/spring/web/dto/CommentRequestDTO.java index 5ad90d6..96e1ee7 100644 --- a/src/main/java/friend/spring/web/dto/CommentRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentRequestDTO.java @@ -18,4 +18,13 @@ public static class commentCreateReq { String content; Long parentId; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class commentEditReq { + @NotBlank + String content; + } } From bb2cb6373a522564ae4b4a6cd05111f98775523c Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Wed, 31 Jan 2024 12:03:54 +0900 Subject: [PATCH 076/255] =?UTF-8?q?#32=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/web/controller/CommentRestController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 3bc05bf..2573e0c 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -145,12 +145,14 @@ public ApiResponse selectComment( } // 댓글 수정 - @PostMapping("/{post-id}/comment/{comment-id}/edit") + @PatchMapping("/{post-id}/comment/{comment-id}/edit") @Operation(summary = "댓글 수정 API", description = "댓글 수정하는 API입니다. ex) /posts/1/comment/1/edit") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4005",description = "올바른 사용자(댓글 작성자)가 아닙니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), From 013e348a333a07e147d246745560f807003a64c6 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 31 Jan 2024 13:15:28 +0900 Subject: [PATCH 077/255] =?UTF-8?q?#31=20Feat:general=20vote=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80(=EB=AF=B8=EC=99=84=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../converter/General_PollConverter.java | 2 +- .../spring/converter/VoteConverter.java | 31 +++++++ .../friend/spring/domain/General_poll.java | 5 +- .../friend/spring/domain/General_vote.java | 93 ++++++------------- src/main/java/friend/spring/domain/Post.java | 2 - .../repository/General_VoteRepository.java | 7 ++ .../friend/spring/service/VoteService.java | 11 +++ .../spring/service/VoteServiceImpl.java | 48 ++++++++++ .../web/controller/VoteRestController.java | 30 ++++++ .../friend/spring/web/dto/VoteRequestDTO.java | 15 +++ .../spring/web/dto/VoteResponseDTO.java | 19 ++++ 11 files changed, 191 insertions(+), 72 deletions(-) create mode 100644 src/main/java/friend/spring/converter/VoteConverter.java create mode 100644 src/main/java/friend/spring/repository/General_VoteRepository.java create mode 100644 src/main/java/friend/spring/service/VoteService.java create mode 100644 src/main/java/friend/spring/service/VoteServiceImpl.java create mode 100644 src/main/java/friend/spring/web/controller/VoteRestController.java create mode 100644 src/main/java/friend/spring/web/dto/VoteRequestDTO.java create mode 100644 src/main/java/friend/spring/web/dto/VoteResponseDTO.java diff --git a/src/main/java/friend/spring/converter/General_PollConverter.java b/src/main/java/friend/spring/converter/General_PollConverter.java index 7f38570..156dc62 100644 --- a/src/main/java/friend/spring/converter/General_PollConverter.java +++ b/src/main/java/friend/spring/converter/General_PollConverter.java @@ -7,7 +7,7 @@ public class General_PollConverter { - public static General_poll toGeneralVoteList(List pollOptions) { + public static General_poll toGeneralPollList(List pollOptions) { return General_poll.builder() .candidateList(pollOptions) .build(); diff --git a/src/main/java/friend/spring/converter/VoteConverter.java b/src/main/java/friend/spring/converter/VoteConverter.java new file mode 100644 index 0000000..5777b69 --- /dev/null +++ b/src/main/java/friend/spring/converter/VoteConverter.java @@ -0,0 +1,31 @@ +package friend.spring.converter; + +import friend.spring.domain.General_vote; +import friend.spring.domain.Post; +import friend.spring.domain.enums.PostCategory; +import friend.spring.domain.enums.PostState; +import friend.spring.domain.enums.PostType; +import friend.spring.domain.enums.PostVoteType; +import friend.spring.web.dto.PostRequestDTO; +import friend.spring.web.dto.PostResponseDTO; +import friend.spring.web.dto.VoteRequestDTO; +import friend.spring.web.dto.VoteResponseDTO; + +import java.time.LocalDateTime; + +import static friend.spring.domain.enums.PostType.VOTE; + +public class VoteConverter { + public static VoteResponseDTO.GeneralVoteResponseDTO toAddGeneralVoteResultDTO(General_vote generalVote) { + return VoteResponseDTO.GeneralVoteResponseDTO.builder() + .generalVoteId(generalVote.getId()) + .createdAt(LocalDateTime.now()) + .build(); + } + + public static General_vote toGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request) { + + return General_vote.builder() + .build(); + } +} diff --git a/src/main/java/friend/spring/domain/General_poll.java b/src/main/java/friend/spring/domain/General_poll.java index 5eb3b5e..4f91248 100644 --- a/src/main/java/friend/spring/domain/General_poll.java +++ b/src/main/java/friend/spring/domain/General_poll.java @@ -26,9 +26,8 @@ public class General_poll extends BaseEntity { @JoinColumn(name = "user_id") private User user; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "general_vote_id") - private General_vote generalVote; + @OneToMany(mappedBy = "generalPoll", cascade = CascadeType.ALL) + private List generalVoteList = new ArrayList<>(); @OneToOne(mappedBy = "generalPoll", cascade = CascadeType.ALL) private Post post; diff --git a/src/main/java/friend/spring/domain/General_vote.java b/src/main/java/friend/spring/domain/General_vote.java index 662c795..a8857d8 100644 --- a/src/main/java/friend/spring/domain/General_vote.java +++ b/src/main/java/friend/spring/domain/General_vote.java @@ -17,74 +17,35 @@ public class General_vote extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false) - private String candidate1; - - @Column(nullable = true) - private String candidate2; - - @Column(nullable = true) - private String candidate3; - - @Column(nullable = true) - private String candidate4; - - @Column(nullable = true) - private String candidate5; - - @Column(nullable = true) - private String candidate6; - - @Column(nullable = true) - private String candidate7; - - @Column(nullable = true) - private String candidate8; - - @Column(nullable = true) - private String candidate9; - - @Column(nullable = true) - private String candidate10; - - @Column(nullable = true) - private String c1_img; - - @Column(nullable = true) - private String c2_img; - - @Column(nullable = true) - private String c3_img; - - @Column(nullable = true) - private String c4_img; - - @Column(nullable = true) - private String c5_img; - - @Column(nullable = true) - private String c6_img; - - @Column(nullable = true) - private String c7_img; - - @Column(nullable = true) - private String c8_img; - - @Column(nullable = true) - private String c9_img; - - @Column(nullable = true) - private String c10_img; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "post_id") - private Post post; - - @OneToMany(mappedBy = "generalVote") - private List generalPollList = new ArrayList<>(); + @ElementCollection + @Column(nullable = true, length = 100) + private List select_list=new ArrayList(); @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "general_poll_id") + private General_poll generalPoll; + + public void setSelect_list(List select_list) { + if (select_list != null) { + this.select_list = new ArrayList(select_list); + } else { + this.select_list.clear(); + } + } + public void setGeneralPoll(General_poll generalPoll){ + if(this.generalPoll != null) + generalPoll.getGeneralVoteList().remove(this); + this.generalPoll = generalPoll; + generalPoll.getGeneralVoteList().add(this); + } + public void setUser(User user){ + if(this.user != null) + user.getGeneralVoteList().remove(this); + this.user = user; + user.getGeneralVoteList().add(this); + } } diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 8232247..05c111a 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -41,8 +41,6 @@ public class Post extends BaseEntity { @Enumerated(EnumType.STRING) private PostCategory category; -// @Column(nullable = true, length = 1000) -// private String file; @ElementCollection @Column(nullable = true, length = 100) diff --git a/src/main/java/friend/spring/repository/General_VoteRepository.java b/src/main/java/friend/spring/repository/General_VoteRepository.java new file mode 100644 index 0000000..532d41a --- /dev/null +++ b/src/main/java/friend/spring/repository/General_VoteRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.General_vote; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface General_VoteRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/service/VoteService.java b/src/main/java/friend/spring/service/VoteService.java new file mode 100644 index 0000000..904779d --- /dev/null +++ b/src/main/java/friend/spring/service/VoteService.java @@ -0,0 +1,11 @@ +package friend.spring.service; + +import friend.spring.domain.General_vote; +import friend.spring.domain.Post; +import friend.spring.web.dto.PostRequestDTO; +import friend.spring.web.dto.VoteRequestDTO; + +public interface VoteService { + + General_vote castVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId); +} diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java new file mode 100644 index 0000000..dd7c117 --- /dev/null +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -0,0 +1,48 @@ +package friend.spring.service; + +import friend.spring.converter.VoteConverter; +import friend.spring.domain.*; +import friend.spring.repository.*; +import friend.spring.web.dto.VoteRequestDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class VoteServiceImpl implements VoteService{ + private final UserRepository userRepository; + private final General_VoteRepository generalVoteRepository; + private final PostRepository postRepository; + @Override + @Transactional + public General_vote castVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId) { + General_vote newGeneralVote = VoteConverter.toGeneralVote(request); + User user = userRepository.findById(userId) + .orElseThrow(() -> new RuntimeException("\"" + userId + "\"해당 유저가 없습니다")); + newGeneralVote.setUser(user); + + Post post=postRepository.findById(request.getPostId()) + .orElseThrow(()-> new RuntimeException("\"" + request.getPostId() + "\"해당 글이 없습니다")); + + General_poll generalPoll=post.getGeneralPoll(); + + List selectedCandidateIds = request.getSelectList(); + List validCandidateIds = generalPoll.getCandidateList().stream() + .map(Candidate::getId) + .collect(Collectors.toList()); + for (Long selectedId : selectedCandidateIds) { + if (!validCandidateIds.contains(selectedId)) { + throw new RuntimeException("해당 후보 ID가 존재하지 않습니다: " + selectedId); + } + } + + if (request.getSelectList() != null) { + newGeneralVote.setSelect_list(request.getSelectList()); + } + return generalVoteRepository.save(newGeneralVote); + } +} diff --git a/src/main/java/friend/spring/web/controller/VoteRestController.java b/src/main/java/friend/spring/web/controller/VoteRestController.java new file mode 100644 index 0000000..cdc45af --- /dev/null +++ b/src/main/java/friend/spring/web/controller/VoteRestController.java @@ -0,0 +1,30 @@ +package friend.spring.web.controller; + +import friend.spring.apiPayload.ApiResponse; +import friend.spring.converter.VoteConverter; +import friend.spring.domain.General_vote; +import friend.spring.service.VoteService; +import friend.spring.web.dto.VoteRequestDTO; +import friend.spring.web.dto.VoteResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +@RestController +@RequiredArgsConstructor +@Validated +@RequestMapping("/posts") +public class VoteRestController { + private final VoteService voteService; + @PostMapping("/{post-id}/{user-id}/normalVote") + @Operation(summary = "일반 투표 API", description = "임시로 user-id 입력") + public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GeneralVoteRequestDTO request, + @PathVariable(name="user-id")Long UserId){ + General_vote generalVote= voteService.castVote(request,UserId); + return ApiResponse.onSuccess(VoteConverter.toAddGeneralVoteResultDTO(generalVote)); + } +} + diff --git a/src/main/java/friend/spring/web/dto/VoteRequestDTO.java b/src/main/java/friend/spring/web/dto/VoteRequestDTO.java new file mode 100644 index 0000000..16d39ce --- /dev/null +++ b/src/main/java/friend/spring/web/dto/VoteRequestDTO.java @@ -0,0 +1,15 @@ +package friend.spring.web.dto; + +import lombok.Getter; + +import javax.validation.constraints.NotBlank; +import java.sql.Timestamp; +import java.util.List; + +public class VoteRequestDTO { + @Getter + public static class GeneralVoteRequestDTO{ + Long postId; + List selectList; + } +} diff --git a/src/main/java/friend/spring/web/dto/VoteResponseDTO.java b/src/main/java/friend/spring/web/dto/VoteResponseDTO.java new file mode 100644 index 0000000..e95f698 --- /dev/null +++ b/src/main/java/friend/spring/web/dto/VoteResponseDTO.java @@ -0,0 +1,19 @@ +package friend.spring.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +public class VoteResponseDTO { + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class GeneralVoteResponseDTO { + Long generalVoteId; + LocalDateTime createdAt; + } +} From f6186cb2c25d0d68d9d7f2d07de90ee855567da8 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Wed, 31 Jan 2024 14:39:18 +0900 Subject: [PATCH 078/255] =?UTF-8?q?#32=20Refactor:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20state=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Comment.java | 6 ++++++ src/main/java/friend/spring/domain/Post.java | 2 +- src/main/java/friend/spring/domain/enums/CommentState.java | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/main/java/friend/spring/domain/enums/CommentState.java diff --git a/src/main/java/friend/spring/domain/Comment.java b/src/main/java/friend/spring/domain/Comment.java index 109b062..2df28c9 100644 --- a/src/main/java/friend/spring/domain/Comment.java +++ b/src/main/java/friend/spring/domain/Comment.java @@ -1,6 +1,8 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; +import friend.spring.domain.enums.CommentState; +import friend.spring.domain.enums.PostState; import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import lombok.*; @@ -22,6 +24,10 @@ public class Comment extends BaseEntity { @Column(nullable = false, length = 500) private String content; + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private CommentState state; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 9e110a3..de1eb36 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -45,7 +45,7 @@ public class Post extends BaseEntity { private String tag; @Enumerated(EnumType.STRING) - @Column + @Column(nullable = false) private PostState state; @Column(nullable = false) diff --git a/src/main/java/friend/spring/domain/enums/CommentState.java b/src/main/java/friend/spring/domain/enums/CommentState.java new file mode 100644 index 0000000..a684c97 --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/CommentState.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum CommentState { + DELETED, POSTING +} From 9e78726e2dbb41bee69c15e394a927695394bf1d Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Wed, 31 Jan 2024 14:39:54 +0900 Subject: [PATCH 079/255] =?UTF-8?q?#32=20Refactor:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20state=20=EC=86=8D=EC=84=B1=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Comment.java | 2 +- src/main/java/friend/spring/domain/Post.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/friend/spring/domain/Comment.java b/src/main/java/friend/spring/domain/Comment.java index 2df28c9..a7f8cea 100644 --- a/src/main/java/friend/spring/domain/Comment.java +++ b/src/main/java/friend/spring/domain/Comment.java @@ -25,7 +25,7 @@ public class Comment extends BaseEntity { private String content; @Enumerated(EnumType.STRING) - @Column(nullable = false) + @Column private CommentState state; @ManyToOne(fetch = FetchType.LAZY) diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index de1eb36..9e110a3 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -45,7 +45,7 @@ public class Post extends BaseEntity { private String tag; @Enumerated(EnumType.STRING) - @Column(nullable = false) + @Column private PostState state; @Column(nullable = false) From 433cda74f27fa0f5af5ee9b1a222434695176fb8 Mon Sep 17 00:00:00 2001 From: hjh <98207658+jjjuhoon@users.noreply.github.com> Date: Wed, 31 Jan 2024 16:06:20 +0900 Subject: [PATCH 080/255] =?UTF-8?q?#34=20Feat:Gauge=20vote=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80(=EB=AF=B8=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/VoteConverter.java | 8 ++++++++ .../java/friend/spring/domain/Gauge_poll.java | 2 +- .../java/friend/spring/domain/Gauge_vote.java | 19 ++++++++++++++++++- .../spring/service/VoteServiceImpl.java | 1 + .../friend/spring/web/dto/VoteRequestDTO.java | 7 +++++++ 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/main/java/friend/spring/converter/VoteConverter.java b/src/main/java/friend/spring/converter/VoteConverter.java index 5777b69..bef62db 100644 --- a/src/main/java/friend/spring/converter/VoteConverter.java +++ b/src/main/java/friend/spring/converter/VoteConverter.java @@ -1,5 +1,6 @@ package friend.spring.converter; +import friend.spring.domain.Gauge_vote; import friend.spring.domain.General_vote; import friend.spring.domain.Post; import friend.spring.domain.enums.PostCategory; @@ -28,4 +29,11 @@ public static General_vote toGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO re return General_vote.builder() .build(); } + + public static Gauge_vote toGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request) { + + return Gauge_vote.builder() + .value(request.getValue()) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/Gauge_poll.java b/src/main/java/friend/spring/domain/Gauge_poll.java index 53c00d5..8dea793 100644 --- a/src/main/java/friend/spring/domain/Gauge_poll.java +++ b/src/main/java/friend/spring/domain/Gauge_poll.java @@ -36,7 +36,7 @@ public class Gauge_poll extends BaseEntity { private Post post; @Builder.Default - @OneToMany(mappedBy = "gaugeQuestion") + @OneToMany(mappedBy = "gaugePoll") private List gaugeVoteList = new ArrayList<>(); public void setPost(Post post) { diff --git a/src/main/java/friend/spring/domain/Gauge_vote.java b/src/main/java/friend/spring/domain/Gauge_vote.java index 3b041af..97ca4c8 100644 --- a/src/main/java/friend/spring/domain/Gauge_vote.java +++ b/src/main/java/friend/spring/domain/Gauge_vote.java @@ -18,11 +18,28 @@ public class Gauge_vote extends BaseEntity { @Column(nullable = false) private Integer gauge; + @Column(nullable = false) + private Integer value=0; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "gauge_question_id") - private Gauge_poll gaugeQuestion; + private Gauge_poll gaugePoll; + + + public void setGaugePoll(Gauge_poll gaugePoll){ + if(this.gaugePoll != null) + gaugePoll.getGaugeVoteList().remove(this); + this.gaugePoll = gaugePoll; + gaugePoll.getGaugeVoteList().add(this); + } + public void setUser(User user){ + if(this.user != null) + user.getGaugeVoteList().remove(this); + this.user = user; + user.getGaugeVoteList().add(this); + } } diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index dd7c117..c5d3b6a 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -29,6 +29,7 @@ public General_vote castVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long .orElseThrow(()-> new RuntimeException("\"" + request.getPostId() + "\"해당 글이 없습니다")); General_poll generalPoll=post.getGeneralPoll(); + newGeneralVote.setGeneralPoll(generalPoll); List selectedCandidateIds = request.getSelectList(); List validCandidateIds = generalPoll.getCandidateList().stream() diff --git a/src/main/java/friend/spring/web/dto/VoteRequestDTO.java b/src/main/java/friend/spring/web/dto/VoteRequestDTO.java index 16d39ce..9e0cc05 100644 --- a/src/main/java/friend/spring/web/dto/VoteRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/VoteRequestDTO.java @@ -12,4 +12,11 @@ public static class GeneralVoteRequestDTO{ Long postId; List selectList; } + + @Getter + public static class GaugeVoteRequestDTO{ + Long postId; + Integer value; + } + } From 40983402e6add456366a79c09de4efbc17f36161 Mon Sep 17 00:00:00 2001 From: hjh <98207658+jjjuhoon@users.noreply.github.com> Date: Wed, 31 Jan 2024 16:56:01 +0900 Subject: [PATCH 081/255] =?UTF-8?q?#34=20Feat:Gauge=20vote=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/VoteConverter.java | 7 +++++++ .../java/friend/spring/domain/Gauge_poll.java | 2 +- .../java/friend/spring/domain/Gauge_vote.java | 5 +---- .../repository/Gauge_VoteRepository.java | 8 +++++++ .../spring/service/PostServiceImpl.java | 2 +- .../friend/spring/service/VoteService.java | 6 +++--- .../spring/service/VoteServiceImpl.java | 21 ++++++++++++++++++- .../web/controller/PostRestController.java | 2 +- .../web/controller/VoteRestController.java | 13 ++++++++++-- .../spring/web/dto/VoteResponseDTO.java | 9 ++++++++ src/main/resources/application.yml | 2 +- 11 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 src/main/java/friend/spring/repository/Gauge_VoteRepository.java diff --git a/src/main/java/friend/spring/converter/VoteConverter.java b/src/main/java/friend/spring/converter/VoteConverter.java index bef62db..be8595a 100644 --- a/src/main/java/friend/spring/converter/VoteConverter.java +++ b/src/main/java/friend/spring/converter/VoteConverter.java @@ -24,6 +24,13 @@ public static VoteResponseDTO.GeneralVoteResponseDTO toAddGeneralVoteResultDTO(G .build(); } + public static VoteResponseDTO.GaugeVoteResponseDTO toAddGaugelVoteResultDTO(Gauge_vote gaugeVote) { + return VoteResponseDTO.GaugeVoteResponseDTO.builder() + .gaugeVoteId(gaugeVote.getId()) + .createdAt(LocalDateTime.now()) + .build(); + } + public static General_vote toGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request) { return General_vote.builder() diff --git a/src/main/java/friend/spring/domain/Gauge_poll.java b/src/main/java/friend/spring/domain/Gauge_poll.java index 8dea793..26e0e8a 100644 --- a/src/main/java/friend/spring/domain/Gauge_poll.java +++ b/src/main/java/friend/spring/domain/Gauge_poll.java @@ -26,7 +26,7 @@ public class Gauge_poll extends BaseEntity { private Integer max=100; @Column(nullable = false) - private Integer value=0; + private Integer gauge =0; @Column(nullable = true) private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. diff --git a/src/main/java/friend/spring/domain/Gauge_vote.java b/src/main/java/friend/spring/domain/Gauge_vote.java index 97ca4c8..a6cc42b 100644 --- a/src/main/java/friend/spring/domain/Gauge_vote.java +++ b/src/main/java/friend/spring/domain/Gauge_vote.java @@ -15,9 +15,6 @@ public class Gauge_vote extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false) - private Integer gauge; - @Column(nullable = false) private Integer value=0; @@ -26,7 +23,7 @@ public class Gauge_vote extends BaseEntity { private User user; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "gauge_question_id") + @JoinColumn(name = "gauge_poll_id") private Gauge_poll gaugePoll; diff --git a/src/main/java/friend/spring/repository/Gauge_VoteRepository.java b/src/main/java/friend/spring/repository/Gauge_VoteRepository.java new file mode 100644 index 0000000..0525e8e --- /dev/null +++ b/src/main/java/friend/spring/repository/Gauge_VoteRepository.java @@ -0,0 +1,8 @@ +package friend.spring.repository; + +import friend.spring.domain.Gauge_poll; +import friend.spring.domain.Gauge_vote; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface Gauge_VoteRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 0cf0066..5b7ba95 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -90,7 +90,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { Gauge_poll gaugePoll = Gauge_poll.builder() .max(100) .min(0) - .value(0) + .gauge(0) .deadline(request.getDeadline()) .build(); diff --git a/src/main/java/friend/spring/service/VoteService.java b/src/main/java/friend/spring/service/VoteService.java index 904779d..a9dde2f 100644 --- a/src/main/java/friend/spring/service/VoteService.java +++ b/src/main/java/friend/spring/service/VoteService.java @@ -1,11 +1,11 @@ package friend.spring.service; +import friend.spring.domain.Gauge_vote; import friend.spring.domain.General_vote; -import friend.spring.domain.Post; -import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.VoteRequestDTO; public interface VoteService { - General_vote castVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId); + General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId); + Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long userId); } diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index c5d3b6a..ee2b31c 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -16,10 +16,11 @@ public class VoteServiceImpl implements VoteService{ private final UserRepository userRepository; private final General_VoteRepository generalVoteRepository; + private final Gauge_VoteRepository gaugeVoteRepository; private final PostRepository postRepository; @Override @Transactional - public General_vote castVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId) { + public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId) { General_vote newGeneralVote = VoteConverter.toGeneralVote(request); User user = userRepository.findById(userId) .orElseThrow(() -> new RuntimeException("\"" + userId + "\"해당 유저가 없습니다")); @@ -46,4 +47,22 @@ public General_vote castVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long } return generalVoteRepository.save(newGeneralVote); } + + @Override + @Transactional + public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long userId){ + Gauge_vote newGaugeVote = VoteConverter.toGaugeVote(request); + User user = userRepository.findById(userId) + .orElseThrow(() -> new RuntimeException("\"" + userId + "\"해당 유저가 없습니다")); + newGaugeVote.setUser(user); + + Post post=postRepository.findById(request.getPostId()) + .orElseThrow(()-> new RuntimeException("\"" + request.getPostId() + "\"해당 글이 없습니다")); + + Gauge_poll gaugePoll=post.getGaugePoll(); + newGaugeVote.setGaugePoll(gaugePoll); + + return gaugeVoteRepository.save(newGaugeVote); + } + } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 74907c8..f6ab7e5 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -20,7 +20,7 @@ public class PostRestController { @PostMapping("/{user-id}") @Operation(summary = "글 작성 API", description = "PostType = 1 : NOT_VOTE, 2 : VOTE, 3 : REVIEW
" + "Category = 1 : EDUCATION, 2 : ENTERTAINMENT, 3 : LIFESTYLE, 4 : ECONOMY, 5 : SHOPPING, 6 : OTHERS
" + - "postVoteType = 1 : GENERAL, 2 : GAUGE") + "postVoteType = 1 : GENERAL, 2 : GAUGE, 3 : CARD") public ApiResponse join(@RequestBody @Valid PostRequestDTO.AddPostDTO request, @PathVariable(name="user-id")Long UserId){ Post post= postService.joinPost(request,UserId); diff --git a/src/main/java/friend/spring/web/controller/VoteRestController.java b/src/main/java/friend/spring/web/controller/VoteRestController.java index cdc45af..f2b2701 100644 --- a/src/main/java/friend/spring/web/controller/VoteRestController.java +++ b/src/main/java/friend/spring/web/controller/VoteRestController.java @@ -2,6 +2,7 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.VoteConverter; +import friend.spring.domain.Gauge_vote; import friend.spring.domain.General_vote; import friend.spring.service.VoteService; import friend.spring.web.dto.VoteRequestDTO; @@ -19,12 +20,20 @@ @RequestMapping("/posts") public class VoteRestController { private final VoteService voteService; - @PostMapping("/{post-id}/{user-id}/normalVote") + @PostMapping("/{post-id}/{user-id}/generalVote") @Operation(summary = "일반 투표 API", description = "임시로 user-id 입력") public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GeneralVoteRequestDTO request, @PathVariable(name="user-id")Long UserId){ - General_vote generalVote= voteService.castVote(request,UserId); + General_vote generalVote= voteService.castGeneralVote(request,UserId); return ApiResponse.onSuccess(VoteConverter.toAddGeneralVoteResultDTO(generalVote)); } + + @PostMapping("/{post-id}/{user-id}/gaugeVote") + @Operation(summary = "게이지 투표 API", description = "임시로 user-id 입력") + public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GaugeVoteRequestDTO request, + @PathVariable(name="user-id")Long UserId){ + Gauge_vote gaugeVote= voteService.castGaugeVote(request,UserId); + return ApiResponse.onSuccess(VoteConverter.toAddGaugelVoteResultDTO(gaugeVote)); + } } diff --git a/src/main/java/friend/spring/web/dto/VoteResponseDTO.java b/src/main/java/friend/spring/web/dto/VoteResponseDTO.java index e95f698..3fca9c0 100644 --- a/src/main/java/friend/spring/web/dto/VoteResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/VoteResponseDTO.java @@ -16,4 +16,13 @@ public static class GeneralVoteResponseDTO { Long generalVoteId; LocalDateTime createdAt; } + + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class GaugeVoteResponseDTO { + Long gaugeVoteId; + LocalDateTime createdAt; + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index fc07363..d8ad835 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -15,6 +15,6 @@ spring: format_sql: true use_sql_comments: true hbm2ddl: - auto: update + auto: create default_batch_fetch_size: 1000 globally_quoted_identifiers: true \ No newline at end of file From d70eb6bfbf2df1d98ab233297d47fa6b74424421 Mon Sep 17 00:00:00 2001 From: hjh <98207658+jjjuhoon@users.noreply.github.com> Date: Wed, 31 Jan 2024 17:32:16 +0900 Subject: [PATCH 082/255] =?UTF-8?q?#35=20Feat:Card=20vote=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../converter/General_PollConverter.java | 15 --------- .../spring/converter/VoteConverter.java | 14 ++++++++ .../java/friend/spring/domain/Card_poll.java | 14 ++++---- .../java/friend/spring/domain/Card_vote.java | 32 +++++++++++++++++-- .../friend/spring/domain/General_poll.java | 6 ++-- src/main/java/friend/spring/domain/Post.java | 2 -- src/main/java/friend/spring/domain/User.java | 4 +++ .../friend/spring/service/VoteService.java | 4 +++ .../spring/service/VoteServiceImpl.java | 30 +++++++++++++++++ .../web/controller/VoteRestController.java | 9 ++++++ .../friend/spring/web/dto/VoteRequestDTO.java | 5 +++ .../spring/web/dto/VoteResponseDTO.java | 9 ++++++ 12 files changed, 115 insertions(+), 29 deletions(-) delete mode 100644 src/main/java/friend/spring/converter/General_PollConverter.java diff --git a/src/main/java/friend/spring/converter/General_PollConverter.java b/src/main/java/friend/spring/converter/General_PollConverter.java deleted file mode 100644 index 156dc62..0000000 --- a/src/main/java/friend/spring/converter/General_PollConverter.java +++ /dev/null @@ -1,15 +0,0 @@ -package friend.spring.converter; - -import friend.spring.domain.Candidate; -import friend.spring.domain.General_poll; - -import java.util.List; - -public class General_PollConverter { - - public static General_poll toGeneralPollList(List pollOptions) { - return General_poll.builder() - .candidateList(pollOptions) - .build(); - } -} \ No newline at end of file diff --git a/src/main/java/friend/spring/converter/VoteConverter.java b/src/main/java/friend/spring/converter/VoteConverter.java index be8595a..3f8e72d 100644 --- a/src/main/java/friend/spring/converter/VoteConverter.java +++ b/src/main/java/friend/spring/converter/VoteConverter.java @@ -1,5 +1,6 @@ package friend.spring.converter; +import friend.spring.domain.Card_vote; import friend.spring.domain.Gauge_vote; import friend.spring.domain.General_vote; import friend.spring.domain.Post; @@ -31,6 +32,13 @@ public static VoteResponseDTO.GaugeVoteResponseDTO toAddGaugelVoteResultDTO(Gaug .build(); } + public static VoteResponseDTO.CardVoteResponseDTO toAddCardVoteResultDTO(Card_vote cardVote) { + return VoteResponseDTO.CardVoteResponseDTO.builder() + .cardVoteId(cardVote.getId()) + .createdAt(LocalDateTime.now()) + .build(); + } + public static General_vote toGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request) { return General_vote.builder() @@ -43,4 +51,10 @@ public static Gauge_vote toGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request) .value(request.getValue()) .build(); } + + public static Card_vote toCardVote(VoteRequestDTO.CardVoteRequestDTO request) { + + return Card_vote.builder() + .build(); + } } diff --git a/src/main/java/friend/spring/domain/Card_poll.java b/src/main/java/friend/spring/domain/Card_poll.java index a490fca..7cb243a 100644 --- a/src/main/java/friend/spring/domain/Card_poll.java +++ b/src/main/java/friend/spring/domain/Card_poll.java @@ -1,5 +1,6 @@ package friend.spring.domain; +import friend.spring.domain.common.BaseEntity; import lombok.*; import javax.persistence.*; @@ -12,7 +13,7 @@ @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor -public class Card_poll { +public class Card_poll extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -20,13 +21,12 @@ public class Card_poll { @Column(nullable = true) private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; +// @ManyToOne(fetch = FetchType.LAZY) +// @JoinColumn(name = "user_id") +// private User user; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "card_vote_id") - private Card_vote cardVote; + @OneToMany(mappedBy = "cardPoll", cascade = CascadeType.ALL) + private List cardVoteList = new ArrayList<>(); @OneToOne(mappedBy = "cardPoll", cascade = CascadeType.ALL) private Post post; diff --git a/src/main/java/friend/spring/domain/Card_vote.java b/src/main/java/friend/spring/domain/Card_vote.java index 9f88bc4..0537770 100644 --- a/src/main/java/friend/spring/domain/Card_vote.java +++ b/src/main/java/friend/spring/domain/Card_vote.java @@ -1,23 +1,51 @@ package friend.spring.domain; +import friend.spring.domain.common.BaseEntity; import lombok.*; import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + @Entity @Getter @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor -public class Card_vote { +public class Card_vote extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @ElementCollection + @Column(nullable = true, length = 100) + private List select_list=new ArrayList(); + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "cardPoll_id") + @JoinColumn(name = "card_poll_id") private Card_poll cardPoll; + + public void setSelect_list(List select_list) { + if (select_list != null) { + this.select_list = new ArrayList(select_list); + } else { + this.select_list.clear(); + } + } + public void setCardPoll(Card_poll cardPoll){ + if(this.cardPoll != null) + cardPoll.getCardVoteList().remove(this); + this.cardPoll = cardPoll; + cardPoll.getCardVoteList().add(this); + } + public void setUser(User user){ + if(this.user != null) + user.getCardVoteList().remove(this); + this.user = user; + user.getCardVoteList().add(this); + } } diff --git a/src/main/java/friend/spring/domain/General_poll.java b/src/main/java/friend/spring/domain/General_poll.java index 4f91248..8d92e17 100644 --- a/src/main/java/friend/spring/domain/General_poll.java +++ b/src/main/java/friend/spring/domain/General_poll.java @@ -22,9 +22,9 @@ public class General_poll extends BaseEntity { @Column(nullable = true) private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; +// @ManyToOne(fetch = FetchType.LAZY) +// @JoinColumn(name = "user_id") +// private User user; @OneToMany(mappedBy = "generalPoll", cascade = CascadeType.ALL) private List generalVoteList = new ArrayList<>(); diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 05c111a..ce6a8f8 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -86,8 +86,6 @@ public class Post extends BaseEntity { @OneToMany(mappedBy = "post") private List commentChoiceList = new ArrayList<>(); -// @OneToMany(mappedBy = "post") -// private List generalQuestionList = new ArrayList<>(); @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "cardPoll_id") diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 193e5bd..e09d4d3 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -110,4 +110,8 @@ public class User extends BaseEntity { @Builder.Default @OneToMany(mappedBy = "user") private List gaugeVoteList = new ArrayList<>(); + + @Builder.Default + @OneToMany(mappedBy = "user") + private List cardVoteList = new ArrayList<>(); } diff --git a/src/main/java/friend/spring/service/VoteService.java b/src/main/java/friend/spring/service/VoteService.java index a9dde2f..9254fce 100644 --- a/src/main/java/friend/spring/service/VoteService.java +++ b/src/main/java/friend/spring/service/VoteService.java @@ -1,5 +1,6 @@ package friend.spring.service; +import friend.spring.domain.Card_vote; import friend.spring.domain.Gauge_vote; import friend.spring.domain.General_vote; import friend.spring.web.dto.VoteRequestDTO; @@ -8,4 +9,7 @@ public interface VoteService { General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId); Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long userId); + + Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request, Long userId); + } diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index ee2b31c..8a9a50d 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -17,6 +17,7 @@ public class VoteServiceImpl implements VoteService{ private final UserRepository userRepository; private final General_VoteRepository generalVoteRepository; private final Gauge_VoteRepository gaugeVoteRepository; + private final Card_VoteRepository cardVoteRepository; private final PostRepository postRepository; @Override @Transactional @@ -64,5 +65,34 @@ public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long return gaugeVoteRepository.save(newGaugeVote); } + @Override + @Transactional + public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request, Long userId){ + Card_vote newCardVote = VoteConverter.toCardVote(request); + User user = userRepository.findById(userId) + .orElseThrow(() -> new RuntimeException("\"" + userId + "\"해당 유저가 없습니다")); + newCardVote.setUser(user); + + Post post=postRepository.findById(request.getPostId()) + .orElseThrow(()-> new RuntimeException("\"" + request.getPostId() + "\"해당 글이 없습니다")); + + Card_poll cardPoll=post.getCardPoll(); + newCardVote.setCardPoll(cardPoll); + + List selectedCandidateIds = request.getSelectList(); + List validCandidateIds = cardPoll.getCandidateList().stream() + .map(Candidate::getId) + .collect(Collectors.toList()); + for (Long selectedId : selectedCandidateIds) { + if (!validCandidateIds.contains(selectedId)) { + throw new RuntimeException("해당 후보 ID가 존재하지 않습니다: " + selectedId); + } + } + + if (request.getSelectList() != null) { + newCardVote.setSelect_list(request.getSelectList()); + } + return cardVoteRepository.save(newCardVote); + } } diff --git a/src/main/java/friend/spring/web/controller/VoteRestController.java b/src/main/java/friend/spring/web/controller/VoteRestController.java index f2b2701..7492bd3 100644 --- a/src/main/java/friend/spring/web/controller/VoteRestController.java +++ b/src/main/java/friend/spring/web/controller/VoteRestController.java @@ -2,6 +2,7 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.VoteConverter; +import friend.spring.domain.Card_vote; import friend.spring.domain.Gauge_vote; import friend.spring.domain.General_vote; import friend.spring.service.VoteService; @@ -35,5 +36,13 @@ public ApiResponse join(@RequestBody @Vali Gauge_vote gaugeVote= voteService.castGaugeVote(request,UserId); return ApiResponse.onSuccess(VoteConverter.toAddGaugelVoteResultDTO(gaugeVote)); } + + @PostMapping("/{post-id}/{user-id}/cardVote") + @Operation(summary = "카드 투표 API", description = "임시로 user-id 입력") + public ApiResponse join(@RequestBody @Valid VoteRequestDTO.CardVoteRequestDTO request, + @PathVariable(name="user-id")Long UserId){ + Card_vote cardVote= voteService.castCardVote(request,UserId); + return ApiResponse.onSuccess(VoteConverter.toAddCardVoteResultDTO(cardVote)); + } } diff --git a/src/main/java/friend/spring/web/dto/VoteRequestDTO.java b/src/main/java/friend/spring/web/dto/VoteRequestDTO.java index 9e0cc05..e7c856c 100644 --- a/src/main/java/friend/spring/web/dto/VoteRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/VoteRequestDTO.java @@ -19,4 +19,9 @@ public static class GaugeVoteRequestDTO{ Integer value; } + @Getter + public static class CardVoteRequestDTO{ + Long postId; + List selectList; + } } diff --git a/src/main/java/friend/spring/web/dto/VoteResponseDTO.java b/src/main/java/friend/spring/web/dto/VoteResponseDTO.java index 3fca9c0..501f604 100644 --- a/src/main/java/friend/spring/web/dto/VoteResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/VoteResponseDTO.java @@ -25,4 +25,13 @@ public static class GaugeVoteResponseDTO { Long gaugeVoteId; LocalDateTime createdAt; } + + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class CardVoteResponseDTO { + Long cardVoteId; + LocalDateTime createdAt; + } } From c7d844ca417b4a561bfe44c0ba3826bcaa04aa5b Mon Sep 17 00:00:00 2001 From: hjh <98207658+jjjuhoon@users.noreply.github.com> Date: Wed, 31 Jan 2024 17:42:31 +0900 Subject: [PATCH 083/255] =?UTF-8?q?#35=20Feat:Card=20vote=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80(+=EC=A3=BC=EC=84=9D=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Card_poll.java | 4 ---- src/main/java/friend/spring/domain/General_poll.java | 4 ---- .../friend/spring/repository/Card_VoteRepository.java | 8 ++++++++ 3 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 src/main/java/friend/spring/repository/Card_VoteRepository.java diff --git a/src/main/java/friend/spring/domain/Card_poll.java b/src/main/java/friend/spring/domain/Card_poll.java index 7cb243a..ba8b090 100644 --- a/src/main/java/friend/spring/domain/Card_poll.java +++ b/src/main/java/friend/spring/domain/Card_poll.java @@ -21,10 +21,6 @@ public class Card_poll extends BaseEntity { @Column(nullable = true) private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. -// @ManyToOne(fetch = FetchType.LAZY) -// @JoinColumn(name = "user_id") -// private User user; - @OneToMany(mappedBy = "cardPoll", cascade = CascadeType.ALL) private List cardVoteList = new ArrayList<>(); diff --git a/src/main/java/friend/spring/domain/General_poll.java b/src/main/java/friend/spring/domain/General_poll.java index 8d92e17..82219d8 100644 --- a/src/main/java/friend/spring/domain/General_poll.java +++ b/src/main/java/friend/spring/domain/General_poll.java @@ -22,10 +22,6 @@ public class General_poll extends BaseEntity { @Column(nullable = true) private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. -// @ManyToOne(fetch = FetchType.LAZY) -// @JoinColumn(name = "user_id") -// private User user; - @OneToMany(mappedBy = "generalPoll", cascade = CascadeType.ALL) private List generalVoteList = new ArrayList<>(); diff --git a/src/main/java/friend/spring/repository/Card_VoteRepository.java b/src/main/java/friend/spring/repository/Card_VoteRepository.java new file mode 100644 index 0000000..e45b383 --- /dev/null +++ b/src/main/java/friend/spring/repository/Card_VoteRepository.java @@ -0,0 +1,8 @@ +package friend.spring.repository; + +import friend.spring.domain.Card_vote; +import friend.spring.domain.Gauge_poll; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface Card_VoteRepository extends JpaRepository { +} From 9bdf98a0afb431fc8865adcfdacbd9c541d155d9 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Wed, 31 Jan 2024 17:44:45 +0900 Subject: [PATCH 084/255] =?UTF-8?q?#4=20Feat:=EC=9D=B4=EB=A9=94=EC=9D=BC?= =?UTF-8?q?=20=EC=9D=B8=EC=A6=9D=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 14 +- src/main/java/friend/spring/Application.java | 8 +- .../spring/apiPayload/ExceptionAdvice.java | 15 +- .../apiPayload/code/ErrorReasonDTO.java | 4 + .../apiPayload/code/status/ErrorStatus.java | 3 +- .../friend/spring/config/EmailConfig.java | 4 +- .../java/friend/spring/config/RedisUtil.java | 32 ++++ .../spring/config/WebSecurityConfig.java | 53 ++++++ .../spring/converter/UserConverter.java | 6 + src/main/java/friend/spring/domain/User.java | 52 +++++- .../spring/repository/UserRepository.java | 7 +- .../security/JwtAuthenticationFilter.java | 50 ++++++ .../spring/security/JwtTokenProvider.java | 165 ++++++++++++++++++ .../security/PrincipalDetailService.java | 20 +++ .../friend/spring/security/TokenType.java | 6 + .../friend/spring/service/EmailService.java | 85 +++++++++ .../spring/service/UserServiceImpl.java | 10 +- .../web/controller/UserRestController.java | 21 +++ .../java/friend/spring/web/dto/TokenDTO.java | 16 ++ .../friend/spring/web/dto/UserRequestDTO.java | 52 ++++-- .../spring/web/dto/UserResponseDTO.java | 34 +++- src/main/resources/application.yml | 58 +++--- 22 files changed, 639 insertions(+), 76 deletions(-) create mode 100644 src/main/java/friend/spring/config/RedisUtil.java create mode 100644 src/main/java/friend/spring/config/WebSecurityConfig.java create mode 100644 src/main/java/friend/spring/security/JwtAuthenticationFilter.java create mode 100644 src/main/java/friend/spring/security/JwtTokenProvider.java create mode 100644 src/main/java/friend/spring/security/PrincipalDetailService.java create mode 100644 src/main/java/friend/spring/security/TokenType.java create mode 100644 src/main/java/friend/spring/service/EmailService.java create mode 100644 src/main/java/friend/spring/web/dto/TokenDTO.java diff --git a/build.gradle b/build.gradle index c070512..24f0944 100644 --- a/build.gradle +++ b/build.gradle @@ -32,15 +32,17 @@ dependencies { implementation 'io.springfox:springfox-swagger2:2.9.2' implementation 'io.springfox:springfox-swagger-ui:2.9.2' + //user + implementation 'com.google.code.findbugs:jsr305:3.0.2' //mail implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2' - implementation group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: '2.5.1' //jwt - testImplementation 'org.springframework.security:spring-security-test' - implementation 'io.jsonwebtoken:jjwt-api:0.12.3' - implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' - implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' - + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.4' + runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.4' + runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.4' +// redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' // S3 implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' implementation platform('software.amazon.awssdk:bom:2.20.56') diff --git a/src/main/java/friend/spring/Application.java b/src/main/java/friend/spring/Application.java index 401acbc..060cbb0 100644 --- a/src/main/java/friend/spring/Application.java +++ b/src/main/java/friend/spring/Application.java @@ -4,7 +4,13 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -@SpringBootApplication +@SpringBootApplication( + exclude = { + org.springframework.cloud.aws.autoconfigure.context.ContextInstanceDataAutoConfiguration.class, + org.springframework.cloud.aws.autoconfigure.context.ContextStackAutoConfiguration.class, + org.springframework.cloud.aws.autoconfigure.context.ContextRegionProviderAutoConfiguration.class + } +) @EnableJpaAuditing public class Application { diff --git a/src/main/java/friend/spring/apiPayload/ExceptionAdvice.java b/src/main/java/friend/spring/apiPayload/ExceptionAdvice.java index d11c334..f9737d2 100644 --- a/src/main/java/friend/spring/apiPayload/ExceptionAdvice.java +++ b/src/main/java/friend/spring/apiPayload/ExceptionAdvice.java @@ -8,6 +8,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.context.request.ServletWebRequest; @@ -32,7 +33,7 @@ public ResponseEntity validation(ConstraintViolationException e, WebRequ .findFirst() .orElseThrow(() -> new RuntimeException("ConstraintViolationException 추출 도중 에러 발생")); - return handleExceptionInternalConstraint(e, ErrorStatus.valueOf(errorMessage), HttpHeaders.EMPTY,request); + return handleExceptionInternalConstraint(e, ErrorStatus.valueOf(errorMessage), HttpHeaders.EMPTY, request); } @@ -49,26 +50,26 @@ public ResponseEntity handleMethodArgumentNotValid( errors.merge(fieldName, errorMessage, (existingErrorMessage, newErrorMessage) -> existingErrorMessage + ", " + newErrorMessage); }); - return handleExceptionInternalArgs(e,HttpHeaders.EMPTY,ErrorStatus.valueOf("_BAD_REQUEST"),request,errors); + return handleExceptionInternalArgs(e, HttpHeaders.EMPTY, ErrorStatus.valueOf("_BAD_REQUEST"), request, errors); } @org.springframework.web.bind.annotation.ExceptionHandler public ResponseEntity exception(Exception e, WebRequest request) { e.printStackTrace(); - return handleExceptionInternalFalse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(),request, e.getMessage()); + return handleExceptionInternalFalse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(), request, e.getMessage()); } @ExceptionHandler(value = GeneralException.class) public ResponseEntity onThrowException(GeneralException generalException, HttpServletRequest request) { ErrorReasonDTO errorReasonHttpStatus = generalException.getErrorReasonHttpStatus(); - return handleExceptionInternal(generalException,errorReasonHttpStatus,null,request); + return handleExceptionInternal(generalException, errorReasonHttpStatus, null, request); } private ResponseEntity handleExceptionInternal(Exception e, ErrorReasonDTO reason, HttpHeaders headers, HttpServletRequest request) { - ApiResponse body = ApiResponse.onFailure(reason.getCode(),reason.getMessage(),null); + ApiResponse body = ApiResponse.onFailure(reason.getCode(), reason.getMessage(), null); // e.printStackTrace(); WebRequest webRequest = new ServletWebRequest(request); @@ -83,7 +84,7 @@ private ResponseEntity handleExceptionInternal(Exception e, ErrorReasonD private ResponseEntity handleExceptionInternalFalse(Exception e, ErrorStatus errorCommonStatus, HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) { - ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorPoint); + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), errorPoint); return super.handleExceptionInternal( e, body, @@ -95,7 +96,7 @@ private ResponseEntity handleExceptionInternalFalse(Exception e, ErrorSt private ResponseEntity handleExceptionInternalArgs(Exception e, HttpHeaders headers, ErrorStatus errorCommonStatus, WebRequest request, Map errorArgs) { - ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorArgs); + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), errorArgs); return super.handleExceptionInternal( e, body, diff --git a/src/main/java/friend/spring/apiPayload/code/ErrorReasonDTO.java b/src/main/java/friend/spring/apiPayload/code/ErrorReasonDTO.java index 3c805fc..db731d0 100644 --- a/src/main/java/friend/spring/apiPayload/code/ErrorReasonDTO.java +++ b/src/main/java/friend/spring/apiPayload/code/ErrorReasonDTO.java @@ -1,11 +1,15 @@ package friend.spring.apiPayload.code; +import lombok.AllArgsConstructor; import lombok.Builder; +import lombok.Data; import lombok.Getter; import org.springframework.http.HttpStatus; @Builder @Getter +@Data +@AllArgsConstructor public class ErrorReasonDTO { private final HttpStatus httpStatus; private final String code; diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 3ed99ee..6ae6f60 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -26,6 +26,7 @@ public enum ErrorStatus implements BaseErrorCode { INCORRECT_CODE(HttpStatus.UNAUTHORIZED, "USER4005", "인증 코드가 일치하지 않습니다."), EMPTY_JWT(HttpStatus.BAD_REQUEST, "USER4006", "JWT를 입력해주세요."), INVALID_JWT(HttpStatus.UNAUTHORIZED, "USER4007", "유효하지 않은 JWT입니다."), + PASSWORD_INCORRECT(HttpStatus.NOT_FOUND, "USER4008", "비밀번호가 틀렸습니다."), // 글 관련 응답 POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "글을 찾을 수 없습니다."), @@ -58,7 +59,7 @@ public ErrorReasonDTO getReasonHttpStatus() { .build() ; - } + } } diff --git a/src/main/java/friend/spring/config/EmailConfig.java b/src/main/java/friend/spring/config/EmailConfig.java index 910376a..6aa4ff2 100644 --- a/src/main/java/friend/spring/config/EmailConfig.java +++ b/src/main/java/friend/spring/config/EmailConfig.java @@ -13,6 +13,8 @@ @PropertySource(value = {"/application.yml"}, factory = YmlSourceFactory.class) public class EmailConfig { + @Value("${mail.smtp.host}") + private String host; @Value("${mail.smtp.port}") private int port; @Value("${mail.smtp.socketFactoryPort}") @@ -49,7 +51,7 @@ private Properties getMailProperties() pt.put("mail.smtp.starttls.enable", starttls); pt.put("mail.smtp.starttls.required", startlls_required); pt.put("mail.smtp.socketFactory.fallback",fallback); - pt.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); + //pt.put("mail.smtp.socketFactory.class", "javax.net.tls.SSLSocketFactory"); return pt; } } diff --git a/src/main/java/friend/spring/config/RedisUtil.java b/src/main/java/friend/spring/config/RedisUtil.java new file mode 100644 index 0000000..1925cf3 --- /dev/null +++ b/src/main/java/friend/spring/config/RedisUtil.java @@ -0,0 +1,32 @@ +package friend.spring.config; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Service; + +import java.time.Duration; + +@Service +@RequiredArgsConstructor +public class RedisUtil { + + private final StringRedisTemplate redisTemplate;//Redis에 접근하기 위한 Spring의 Redis 템플릿 클래스 + + public String getData(String key){//지정된 키(key)에 해당하는 데이터를 Redis에서 가져오는 메서드 + ValueOperations valueOperations=redisTemplate.opsForValue(); + return valueOperations.get(key); + } + public void setData(String key,String value){//지정된 키(key)에 값을 저장하는 메서드 + ValueOperations valueOperations=redisTemplate.opsForValue(); + valueOperations.set(key,value); + } + public void setDataExpire(String key,String value,long duration){//지정된 키(key)에 값을 저장하고, 지정된 시간(duration) 후에 데이터가 만료되도록 설정하는 메서드 + ValueOperations valueOperations=redisTemplate.opsForValue(); + Duration expireDuration=Duration.ofSeconds(duration); + valueOperations.set(key,value,expireDuration); + } + public void deleteData(String key){//지정된 키(key)에 해당하는 데이터를 Redis에서 삭제하는 메서드 + redisTemplate.delete(key); + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/config/WebSecurityConfig.java b/src/main/java/friend/spring/config/WebSecurityConfig.java new file mode 100644 index 0000000..f29183f --- /dev/null +++ b/src/main/java/friend/spring/config/WebSecurityConfig.java @@ -0,0 +1,53 @@ +package friend.spring.config; + +import friend.spring.security.JwtAuthenticationFilter; +import friend.spring.security.JwtTokenProvider; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +// Spring security 사용하는 경우 Postman 의 접근을 security 가 막기 때문에 설정해주어야 함. +@RequiredArgsConstructor +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + private final JwtTokenProvider jwtTokenProvider; + private final RedisTemplate redisTemplate; + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.httpBasic().disable() // rest api 만을 고려하여 기본 설정은 해제 + .csrf().disable()// csrf 보안 토큰 disable + .formLogin().disable() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // session 사용 X + .and() + .authorizeRequests() + //.antMatchers("/users/test").hasRole("USER") + .antMatchers("/**").permitAll() + .anyRequest().permitAll(); + + http.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider, redisTemplate), UsernamePasswordAuthenticationFilter.class) + .authorizeRequests(); + } +} diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 86f1a40..7fc2d4d 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -15,4 +15,10 @@ public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ .build(); } + + public static UserResponseDTO.EmailSendRes toEmailSendRes(String code) { + return UserResponseDTO.EmailSendRes.builder() + .code(code) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 3a81a58..01ff216 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -7,10 +7,15 @@ import friend.spring.domain.mapping.Post_scrap; import lombok.*; import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; import javax.persistence.*; +import javax.validation.constraints.Email; +import javax.validation.constraints.Pattern; import java.time.LocalDate; import java.util.ArrayList; +import java.util.Collection; import java.util.List; @Entity @@ -18,20 +23,23 @@ @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor -public class User extends BaseEntity { +public class User extends BaseEntity implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, length = 20) - private String pw; + private String password; + @Email////1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 + //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 @Column(nullable = false, length = 50) private String email; @Column(nullable = false, length = 15) private String name; + @Pattern(regexp = "^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$", message = "전화번호 형식이 맞지 않습니다.") @Column(nullable = false, length = 15) private String phone; @@ -46,8 +54,11 @@ public class User extends BaseEntity { @Column(nullable = false) private LocalDate birth; - @Column(nullable = false) - private Boolean event; + @Column(nullable = true) + private Boolean agree_marketing; + + @Column(nullable = true) + private Boolean agree_info; @Column(nullable = true) private String image; @@ -64,6 +75,7 @@ public class User extends BaseEntity { @Column(nullable = false) private Integer like; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "level_id") private Level level; @@ -107,4 +119,36 @@ public class User extends BaseEntity { @Builder.Default @OneToMany(mappedBy = "user") private List gaugeVoteList = new ArrayList<>(); + + // UserDetails 상속 + @Override + public Collection getAuthorities() { + return null; + } + + @Override + public String getUsername() { + return email; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } } + diff --git a/src/main/java/friend/spring/repository/UserRepository.java b/src/main/java/friend/spring/repository/UserRepository.java index 6c1e105..370db18 100644 --- a/src/main/java/friend/spring/repository/UserRepository.java +++ b/src/main/java/friend/spring/repository/UserRepository.java @@ -10,10 +10,5 @@ public interface UserRepository extends JpaRepository { Optional findByEmail(String email); - -// Optional findByEmailAndPassword(String email, String password); - - Optional findById(Long Id); - - boolean existsById(Long Id); + Optional findByNickname(String nickname); } diff --git a/src/main/java/friend/spring/security/JwtAuthenticationFilter.java b/src/main/java/friend/spring/security/JwtAuthenticationFilter.java new file mode 100644 index 0000000..96f1389 --- /dev/null +++ b/src/main/java/friend/spring/security/JwtAuthenticationFilter.java @@ -0,0 +1,50 @@ +package friend.spring.security; + +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@RequiredArgsConstructor +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + private final JwtTokenProvider jwtTokenProvider; + + private final RedisTemplate redisTemplate; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + + System.out.println("필터 실행"); + // Request Header에서 JWT 토큰 추출 + String token = jwtTokenProvider.resolveToken(request); + + // validateToken으로 토큰 유효성 검사 + if(token != null && jwtTokenProvider.validateToken(token)) { + + // Redis에 해당 access token logout여부를 확인 + String isLogout = (String) redisTemplate.opsForValue().get(token); + + // 로그아웃이 없는(되어 있지 않은) 경우 해당 토큰은 정상적으로 작동하기 + if (ObjectUtils.isEmpty(isLogout)) { + + // token이 유효하면 인증 객체 생성 + Authentication authentication = jwtTokenProvider.getAuthentication(token); + + // SecurityContextHolder.getContext() : 시큐리티의 session 공간 + SecurityContextHolder.getContext().setAuthentication(authentication); + } + + } + filterChain.doFilter(request, response); + + } +} diff --git a/src/main/java/friend/spring/security/JwtTokenProvider.java b/src/main/java/friend/spring/security/JwtTokenProvider.java new file mode 100644 index 0000000..38bf922 --- /dev/null +++ b/src/main/java/friend/spring/security/JwtTokenProvider.java @@ -0,0 +1,165 @@ +package friend.spring.security; + +import ch.qos.logback.core.status.ErrorStatus; +import friend.spring.apiPayload.GeneralException; +import friend.spring.domain.User; +import friend.spring.repository.UserRepository; +import friend.spring.web.dto.TokenDTO; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import java.util.Base64; +import java.util.Date; +import java.util.Optional; + +import static friend.spring.apiPayload.code.status.ErrorStatus.INVALID_JWT; + +@Slf4j +@RequiredArgsConstructor +@Component +@PropertySource(value = {"/application.yml"}) +public class JwtTokenProvider { + + @Value("${spring.jwt.secret}") + private String secretKey; + + private final UserDetailsService userDetailsService; + + private final UserRepository userRepository; + + private final RedisTemplate redisTemplate; + + + // 객체 초기화, secretKey를 Base64로 인코딩 + @PostConstruct + protected void init() { + secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); + } + + // JWT Access 토큰 생성 + public TokenDTO createAccessToken(String email) { + // 토큰 유효시간 30분 + long tokenValidTime = 30 * 60 * 1000L; + + Optional user = userRepository.findByEmail(email); + + Claims claims = Jwts.claims().setSubject(email); // JWT payload에 저장되는 정보단위 + + if(user.isPresent()) { + + claims.put("email", user.get().getEmail()); + } + + Date now = new Date(); + Date expiresTime = new Date(now.getTime() + tokenValidTime); + String token = Jwts.builder() + .setClaims(claims) + .setIssuedAt(now) + .setExpiration(new Date(now.getTime() + tokenValidTime)) + .signWith(SignatureAlgorithm.HS256, secretKey) + .claim("types", "atk") + //.claim("userIdx",user.get().getUserIdx()) + //.claim("role", user.get().getRole()) + .compact(); + return new TokenDTO(String.valueOf(TokenType.atk), token, expiresTime); + } + + // JWT Refresh 토큰 생성 + public TokenDTO createRefreshToken(String email) { + // Refresh 토큰 유효시간 2주 + long tokenValidTime = 60 * 60 * 24 * 14 * 1000L; + + Claims claims = Jwts.claims().setSubject(email); // JWT payload에 저장되는 정보단위 + + Date now = new Date(); + Date expiresTime = new Date(now.getTime() + tokenValidTime); // 토큰 만료 시간 + String token = Jwts.builder() + .setClaims(claims) // 정보 저장 + .setIssuedAt(now) // 토큰 발행 시간 정보 + .setExpiration(expiresTime) // Expire Time 설정 + .signWith(SignatureAlgorithm.HS256, secretKey) // 사용할 암호화 알고리즘과 signature 에 들어갈 secretkey 값 설정 + .claim("types", "rtk") + .compact(); + return new TokenDTO(String.valueOf(TokenType.rtk),token, expiresTime); + } + + // JWT 토큰에서 인증 정보 조회 + public Authentication getAuthentication(String token) { + UserDetails userDetails = userDetailsService.loadUserByUsername(this.getTokenSub(token)); + return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); + } + + // 토큰에서 회원정보 추출 - email (payload의 subject) + public String getTokenSub(String token) { + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); + } + + // Request 의 Header 에서 access token 값 추출 "atk" : "token--" + public String resolveAccessToken(HttpServletRequest request) { + return request.getHeader("atk"); + } + + // 토큰 재발급 때 Header에 rtk를 넣어 요청, 나머지 경우 atk 사용 + public String resolveToken(HttpServletRequest request) { + if (request.getHeader("rtk") != null){ + return request.getHeader("rtk"); + } else { + return request.getHeader("atk"); + } + } + + // 토큰의 유효성 + 만료일자 확인 + public boolean validateToken(String jwtToken) { + try { + Jws claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwtToken); // 토큰의 payload(claim) // Access 토큰의 경우 redis 까지 검사 + if (claims.getBody().get("types").equals("atk")) { + Object isLogOut = redisTemplate.opsForValue().get(jwtToken); // token 을 key 로 value 가져옴 (null 이면 유효 토큰, logout 이면 유효하지 않은 토큰) + // 로그인 시 redis 에 email : refreshtoken 형태로 저장 + // 로그아웃 시 redis 에 accesstoken : logout 형태로 저장 + if (isLogOut != null) { + return false; + } + return !claims.getBody().getExpiration().before(new Date());// 만료안됐으면 true, 만료됐으면 false + } else { + // Refresh 토큰 유효성 검사 + return !claims.getBody().getExpiration().before(new Date()); // 만료안됐으면 true, 만료됐으면 false + } + }catch (Exception e) { + return false; + } + } + + // 토큰 만료 시간 + public Date getExpireTime(String jwtToken) { + Jws claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwtToken); + return claims.getBody().getExpiration(); + } + +// // 토큰에서 회원정보 추출 - userIdx 추출 +// public Long getCurrentUser(HttpServletRequest request) throws GeneralException { // userIdx 가져오기 +// String jwtToken = resolveAccessToken(request); // Request의 header에서 Access 토큰 추출 +// if(!validateToken(jwtToken)) { +// throw new (INVALID_JWT); +// } +// Long userIdx = Long.valueOf(String.valueOf(Jwts.parser() +// .setSigningKey(secretKey) +// .parseClaimsJws(jwtToken) +// .getBody() +// .get("userIdx"))); +// return userIdx; +// } +} diff --git a/src/main/java/friend/spring/security/PrincipalDetailService.java b/src/main/java/friend/spring/security/PrincipalDetailService.java new file mode 100644 index 0000000..199a2fb --- /dev/null +++ b/src/main/java/friend/spring/security/PrincipalDetailService.java @@ -0,0 +1,20 @@ +package friend.spring.security; + +import friend.spring.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PrincipalDetailService implements UserDetailsService { + private final UserRepository userRepository; + + @Override + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { + return userRepository.findByEmail(email) + .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다.")); + } +} diff --git a/src/main/java/friend/spring/security/TokenType.java b/src/main/java/friend/spring/security/TokenType.java new file mode 100644 index 0000000..c35cded --- /dev/null +++ b/src/main/java/friend/spring/security/TokenType.java @@ -0,0 +1,6 @@ +package friend.spring.security; + +public enum TokenType { + atk, rtk +} + diff --git a/src/main/java/friend/spring/service/EmailService.java b/src/main/java/friend/spring/service/EmailService.java new file mode 100644 index 0000000..a837b34 --- /dev/null +++ b/src/main/java/friend/spring/service/EmailService.java @@ -0,0 +1,85 @@ +package friend.spring.service; + +import friend.spring.apiPayload.GeneralException; +import friend.spring.config.RedisUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.util.Random; + +@Service +@RequiredArgsConstructor +public class EmailService { + + @Autowired + private final JavaMailSender emailSender; + @Autowired + private RedisUtil redisUtil; + private int authNumber; + + // 인증코드 체크 + public boolean CheckAuthNum(String email,String authNum){ + if(redisUtil.getData(authNum)==null){ + System.out.println("false1"); + return false; + } + else if(redisUtil.getData(authNum).equals(email)){ + System.out.println("true"); + return true; + } + else{ + System.out.println("false2"); + return false; + } + } + //임의의 6자리 인증 코드생성 + public void makeRandomNumber() { + Random r = new Random(); + String randomNumber = ""; + for(int i = 0; i < 6; i++) { + randomNumber += Integer.toString(r.nextInt(10)); + } + + authNumber = Integer.parseInt(randomNumber); + } + //mail을 어디서 보내는지, 어디로 보내는지 , 인증 번호를 html 형식으로 어떻게 보내는지 작성 + public String joinEmail(String email) { + makeRandomNumber(); + String setFrom = "gominchingu@gmail.com"; // email-config에 설정한 자신의 이메일 주소를 입력 + String toMail = email; + String title = "고민친구 회원 가입 인증 이메일 입니다."; // 이메일 제목 + String content = + "고민친구를 방문해주셔서 감사합니다." + //html 형식으로 작성 ! + "

" + + "인증 번호는 " + authNumber + "입니다." + + "
" + + "인증 코드의 유효시간은 5분 입니다."; //이메일 내용 삽입 + mailSend(setFrom, toMail, title, content); + + return Integer.toString(authNumber); + } + //이메일을 전송합니다. + public void mailSend(String setFrom, String toMail, String title, String content) { + MimeMessage message = emailSender.createMimeMessage();//JavaMailSender 객체를 사용하여 MimeMessage 객체를 생성 + try { + MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8");//이메일 메시지와 관련된 설정을 수행합니다. + // true를 전달하여 multipart 형식의 메시지를 지원하고, "utf-8"을 전달하여 문자 인코딩을 설정 + helper.setFrom(setFrom);//이메일의 발신자 주소 설정 + helper.setTo(toMail);//이메일의 수신자 주소 설정 + helper.setSubject(title);//이메일의 제목을 설정 + helper.setText(content,true);//이메일의 내용 설정 두 번째 매개 변수에 true를 설정하여 html 설정으로한다. + emailSender.send(message); + } catch (MessagingException e) {//이메일 서버에 연결할 수 없거나, 잘못된 이메일 주소를 사용하거나, 인증 오류가 발생하는 등 오류 + // 이러한 경우 MessagingException이 발생 + e.printStackTrace();//e.printStackTrace()는 예외를 기본 오류 스트림에 출력하는 메서드 + } + redisUtil.setDataExpire(Integer.toString(authNumber),toMail,60*5L); + + } + + } \ No newline at end of file diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 26f768a..182fca8 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -1,21 +1,14 @@ package friend.spring.service; -import friend.spring.apiPayload.GeneralException; + import friend.spring.domain.User; import friend.spring.repository.UserRepository; -import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.apiPayload.handler.UserHandler; -import friend.spring.web.dto.UserRequestDTO; import lombok.RequiredArgsConstructor; -import lombok.Value; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; - -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; import java.util.Optional; -import java.util.Random; import static friend.spring.apiPayload.code.status.ErrorStatus.*; @@ -42,4 +35,5 @@ public void checkUser(Boolean flag) { throw new UserHandler(USER_NOT_FOUND); } } + } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 119a3be..4722eac 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -3,11 +3,15 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.UserConverter; import friend.spring.domain.User; +import friend.spring.service.EmailService; import friend.spring.service.UserService; +import friend.spring.web.dto.UserRequestDTO; import friend.spring.web.dto.UserResponseDTO; +import io.swagger.annotations.Api; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import javax.validation.Valid; @RestController @@ -16,10 +20,27 @@ public class UserRestController { private final UserService userService; + private final EmailService mailService; @GetMapping("/my-page") public ApiResponse myPage(@RequestHeader(name = "id") Long userId) { User Page = userService.findMyPage(userId); return ApiResponse.onSuccess(UserConverter.toMypageResDTO(Page)); } + + @PostMapping ("/mailSend")//이메일 인증 코드 전송 + public ApiResponse mailSend(@RequestBody @Valid UserRequestDTO.EmailSendReq emailDto){ + System.out.println("이메일 인증 요청이 들어옴"); + System.out.println("이메일 인증 이메일 :"+emailDto.getEmail()); + + String code = mailService.joinEmail(emailDto.getEmail()); + return ApiResponse.onSuccess(UserConverter.toEmailSendRes(code)); + } + @PostMapping("/mailauthCheck")//이메일 코드 확인 + public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailSendCheckReq emailSendCheckReq){ + + mailService.CheckAuthNum(emailSendCheckReq.getEmail(), emailSendCheckReq.getAuthNum()); + return ApiResponse.onSuccess(null); + + } } diff --git a/src/main/java/friend/spring/web/dto/TokenDTO.java b/src/main/java/friend/spring/web/dto/TokenDTO.java new file mode 100644 index 0000000..1b3bd5b --- /dev/null +++ b/src/main/java/friend/spring/web/dto/TokenDTO.java @@ -0,0 +1,16 @@ +package friend.spring.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.Date; + +@Data +@AllArgsConstructor +public class TokenDTO { + + //1. 로그인 시 토큰을 응답 + private String types; // atk, rtk + private String token; // jwt 토큰 + private Date tokenExpriresTime; // 토큰 만료시간 +} \ No newline at end of file diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 9defea9..11b9ebf 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -1,20 +1,31 @@ package friend.spring.web.dto; +import friend.spring.domain.enums.Gender; import lombok.Getter; import lombok.AllArgsConstructor; -import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import java.time.LocalDate; + public class UserRequestDTO { @NoArgsConstructor @AllArgsConstructor @Getter @Setter - public static class UserJoinRequest{//회원가입 요청 - String email; + public static class UserJoinRequest{// + private String email; + private String password; + private String nickname; + + private Gender gender; + private boolean agree_info; + private boolean agree_marketing; + private LocalDate birth; } @@ -26,12 +37,19 @@ public static class UserLoginRequest{//로그인 요청 String email; String password; } + @NoArgsConstructor @AllArgsConstructor @Getter @Setter - public static class EmailSendRequest{//이메일 전송 요청 - String email; + public static class EmailCheckReq { + + @Email + @NotEmpty(message = "이메일을 입력해 주세요") + private String email; + + @NotEmpty(message = "인증 번호를 입력해 주세요") + private String authNum; } @@ -39,9 +57,8 @@ public static class EmailSendRequest{//이메일 전송 요청 @AllArgsConstructor @Getter @Setter - public static class EmailDupCheckRequest { // 이메일 중복 확인 - String email; - boolean isForJoin; + public static class NicknameCheckReq{ + private String nickname; } @NoArgsConstructor @@ -56,8 +73,21 @@ public static class UserDeleteReq { // 회원 탈퇴 요청 @AllArgsConstructor @Getter @Setter - public static class EmailCodeCheckRequest{ - String email; - String authCode; + public static class EmailSendReq { + @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 + //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 + @NotEmpty(message = "이메일을 입력해 주세요") + private String email; + } + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Setter + public static class EmailSendCheckReq { + @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 + //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 + @NotEmpty(message = "이메일을 입력해 주세요") + private String email; + private String authNum; } } diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index e50954a..58a462e 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -1,7 +1,12 @@ package friend.spring.web.dto; +import friend.spring.domain.User; +import friend.spring.domain.enums.Gender; import lombok.*; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; + public class UserResponseDTO { @Builder @@ -17,7 +22,6 @@ public static class MyPageResDTO { Integer userRecommend; } - public static class EmailDTO { @NoArgsConstructor @AllArgsConstructor @@ -29,5 +33,33 @@ public static class Email { Boolean isCorrected; Boolean ExistEmail; } + + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Setter + public static class UserJoinRes { + private User user; + } + + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Setter + public static class UserInfo { + private String email; + private String nickname; + private Gender gender; + + } } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class EmailSendRes { + private String code; + } + } \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 58bc1ba..67ebde0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,20 +1,10 @@ spring: - mail: - host: smtp.gmail.com - port: 587 - username: ${gamil.username} - password: ${gmail.password} - properties: - mail: - smtp: - auth: true - starttls: - enable: true - required: true - connectiontimeout: 5000 - timeout: 5000 - writetimeout: 5000 - auth-code-expiration-millis: 1800000 # 30 * 60 * 1000 == 30분 + redis: + host: localhost + port: 6379 + jwt: + secret: c4lsdmVybmluZS10ZWNoLXNwcmluZy1ib290LWp3dC10dXRvcmlhbC1zZWNyZXQtc2lsdmVybmluZS10ZWNoLXNwcmluZy1ib290LWp3dC10dXRvcmlhbC1zZWNyZXQK + datasource: url: ${aws.db.url} username: ${aws.db.username} @@ -34,6 +24,8 @@ spring: auto: update default_batch_fetch_size: 1000 globally_quoted_identifiers: true + + cloud: aws: s3: @@ -56,17 +48,23 @@ logging: util: EC2MetadataUtils: error - mail: - smtp: - auth: true - starttls: - required: true - enable: true - socketFactory: - class: javax.net.ssl.SSLSocketFactory - fallback: false - port: 587 - socketFactoryPort: 587 - AdminMail: - id: gominchingu@gmail.com - password: ibjz alpg rhto caxf \ No newline at end of file +mail: + smtp: + host: smtp.gmail.com + auth: true + starttls: + required: true + enable: true + socketFactory: + # class: javax.net.ssl.SocketFactory + fallback: false + port: 587 + socketFactoryPort: 587 + AdminMail: + id: ${gmail.username} + password: ${gmail.password} + + + +# id: gominchingu@gmail.com +# password: yvel mryl hzrm xtgs \ No newline at end of file From 3cc464db78bceed20ca46acd789fad5c9a8003c2 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Wed, 31 Jan 2024 18:16:17 +0900 Subject: [PATCH 085/255] =?UTF-8?q?#develop=20Refactor:=20yml=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3525ad6..cfae2a6 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,11 +4,10 @@ spring: port: 6379 jwt: secret: c4lsdmVybmluZS10ZWNoLXNwcmluZy1ib290LWp3dC10dXRvcmlhbC1zZWNyZXQtc2lsdmVybmluZS10ZWNoLXNwcmluZy1ib290LWp3dC10dXRvcmlhbC1zZWNyZXQK - datasource: - url: jdbc:mysql://localhost:3306/gomin - username: root - password: 1234 + url: ${aws.db.url} + username: ${aws.db.username} + password: ${aws.db.password} driver-class-name: com.mysql.cj.jdbc.Driver sql: init: @@ -21,11 +20,9 @@ spring: format_sql: true use_sql_comments: true hbm2ddl: - auto: create + auto: update default_batch_fetch_size: 1000 globally_quoted_identifiers: true - - cloud: aws: s3: @@ -47,7 +44,6 @@ logging: amazonaws: util: EC2MetadataUtils: error - mail: smtp: host: smtp.gmail.com From 00cc3220615fd6c514c047c544a0678b619fb526 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Wed, 31 Jan 2024 18:28:03 +0900 Subject: [PATCH 086/255] =?UTF-8?q?applicaion=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20CheckAuthNum=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/Application.java | 8 +------- src/main/java/friend/spring/service/EmailService.java | 6 ++++-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/friend/spring/Application.java b/src/main/java/friend/spring/Application.java index 060cbb0..401acbc 100644 --- a/src/main/java/friend/spring/Application.java +++ b/src/main/java/friend/spring/Application.java @@ -4,13 +4,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -@SpringBootApplication( - exclude = { - org.springframework.cloud.aws.autoconfigure.context.ContextInstanceDataAutoConfiguration.class, - org.springframework.cloud.aws.autoconfigure.context.ContextStackAutoConfiguration.class, - org.springframework.cloud.aws.autoconfigure.context.ContextRegionProviderAutoConfiguration.class - } -) +@SpringBootApplication @EnableJpaAuditing public class Application { diff --git a/src/main/java/friend/spring/service/EmailService.java b/src/main/java/friend/spring/service/EmailService.java index a837b34..fd67df6 100644 --- a/src/main/java/friend/spring/service/EmailService.java +++ b/src/main/java/friend/spring/service/EmailService.java @@ -1,6 +1,8 @@ package friend.spring.service; import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.apiPayload.handler.UserHandler; import friend.spring.config.RedisUtil; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; @@ -26,7 +28,7 @@ public class EmailService { public boolean CheckAuthNum(String email,String authNum){ if(redisUtil.getData(authNum)==null){ System.out.println("false1"); - return false; + throw new UserHandler(ErrorStatus.INCORRECT_CODE); } else if(redisUtil.getData(authNum).equals(email)){ System.out.println("true"); @@ -34,7 +36,7 @@ else if(redisUtil.getData(authNum).equals(email)){ } else{ System.out.println("false2"); - return false; + throw new UserHandler(ErrorStatus.INCORRECT_CODE); } } //임의의 6자리 인증 코드생성 From 76ab5ae1f181eb086371a52dc28892be87b6fc63 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Wed, 31 Jan 2024 18:28:45 +0900 Subject: [PATCH 087/255] =?UTF-8?q?#develop=20Refactor:=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20Builder.default=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Card_poll.java | 3 +++ src/main/java/friend/spring/domain/Card_vote.java | 1 + src/main/java/friend/spring/domain/Gauge_poll.java | 4 ++++ src/main/java/friend/spring/domain/Gauge_vote.java | 1 + src/main/java/friend/spring/domain/General_poll.java | 3 +++ src/main/java/friend/spring/domain/General_vote.java | 1 + src/main/java/friend/spring/domain/Post.java | 8 ++++++++ 7 files changed, 21 insertions(+) diff --git a/src/main/java/friend/spring/domain/Card_poll.java b/src/main/java/friend/spring/domain/Card_poll.java index ba8b090..630d144 100644 --- a/src/main/java/friend/spring/domain/Card_poll.java +++ b/src/main/java/friend/spring/domain/Card_poll.java @@ -19,14 +19,17 @@ public class Card_poll extends BaseEntity { private Long id; @Column(nullable = true) + @Builder.Default private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. + @Builder.Default @OneToMany(mappedBy = "cardPoll", cascade = CascadeType.ALL) private List cardVoteList = new ArrayList<>(); @OneToOne(mappedBy = "cardPoll", cascade = CascadeType.ALL) private Post post; + @Builder.Default @OneToMany(mappedBy = "cardPoll",cascade = CascadeType.ALL) private List candidateList=new ArrayList<>(); diff --git a/src/main/java/friend/spring/domain/Card_vote.java b/src/main/java/friend/spring/domain/Card_vote.java index 0537770..d87c532 100644 --- a/src/main/java/friend/spring/domain/Card_vote.java +++ b/src/main/java/friend/spring/domain/Card_vote.java @@ -18,6 +18,7 @@ public class Card_vote extends BaseEntity { private Long id; @ElementCollection + @Builder.Default @Column(nullable = true, length = 100) private List select_list=new ArrayList(); diff --git a/src/main/java/friend/spring/domain/Gauge_poll.java b/src/main/java/friend/spring/domain/Gauge_poll.java index 26e0e8a..9ef422a 100644 --- a/src/main/java/friend/spring/domain/Gauge_poll.java +++ b/src/main/java/friend/spring/domain/Gauge_poll.java @@ -19,15 +19,19 @@ public class Gauge_poll extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Builder.Default @Column(nullable = false) private Integer min=0; + @Builder.Default @Column(nullable = false) private Integer max=100; + @Builder.Default @Column(nullable = false) private Integer gauge =0; + @Builder.Default @Column(nullable = true) private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. diff --git a/src/main/java/friend/spring/domain/Gauge_vote.java b/src/main/java/friend/spring/domain/Gauge_vote.java index a6cc42b..cc5ed3c 100644 --- a/src/main/java/friend/spring/domain/Gauge_vote.java +++ b/src/main/java/friend/spring/domain/Gauge_vote.java @@ -15,6 +15,7 @@ public class Gauge_vote extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Builder.Default @Column(nullable = false) private Integer value=0; diff --git a/src/main/java/friend/spring/domain/General_poll.java b/src/main/java/friend/spring/domain/General_poll.java index 82219d8..901eb3f 100644 --- a/src/main/java/friend/spring/domain/General_poll.java +++ b/src/main/java/friend/spring/domain/General_poll.java @@ -20,14 +20,17 @@ public class General_poll extends BaseEntity { private Long id; @Column(nullable = true) + @Builder.Default private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. + @Builder.Default @OneToMany(mappedBy = "generalPoll", cascade = CascadeType.ALL) private List generalVoteList = new ArrayList<>(); @OneToOne(mappedBy = "generalPoll", cascade = CascadeType.ALL) private Post post; + @Builder.Default @OneToMany(mappedBy = "generalPoll",cascade = CascadeType.ALL) private List candidateList=new ArrayList<>(); diff --git a/src/main/java/friend/spring/domain/General_vote.java b/src/main/java/friend/spring/domain/General_vote.java index a8857d8..5e64a57 100644 --- a/src/main/java/friend/spring/domain/General_vote.java +++ b/src/main/java/friend/spring/domain/General_vote.java @@ -18,6 +18,7 @@ public class General_vote extends BaseEntity { private Long id; @ElementCollection + @Builder.Default @Column(nullable = true, length = 100) private List select_list=new ArrayList(); diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index ce6a8f8..a2d1c57 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -42,6 +42,7 @@ public class Post extends BaseEntity { private PostCategory category; + @Builder.Default @ElementCollection @Column(nullable = true, length = 100) private List tag=new ArrayList<>(); @@ -50,6 +51,7 @@ public class Post extends BaseEntity { @Column private PostState state; + @Builder.Default @Column(nullable = false) private Integer view=0; @@ -67,22 +69,28 @@ public class Post extends BaseEntity { @JoinColumn(name = "parent_id") private Post parentPost; + @Builder.Default // 자식 글 정의 @OneToMany(mappedBy = "parentPost") private List reviewPostList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post") private List alarmList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private List postLikeList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private List postScrapList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post") private List commentList = new ArrayList<>(); + @Builder.Default @OneToMany(mappedBy = "post") private List commentChoiceList = new ArrayList<>(); From d2b28b24780c1e598e8860a310082d8a4a3667ba Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Wed, 31 Jan 2024 18:31:17 +0900 Subject: [PATCH 088/255] =?UTF-8?q?#33=20Docs:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c740e4..8851782 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# BE 고민친구 +# BE <고민친구> ### 커밋 규칙 From f269ed0836fd8a6e813b9d31f837a806048fb3f5 Mon Sep 17 00:00:00 2001 From: hjh Date: Thu, 1 Feb 2024 17:52:06 +0900 Subject: [PATCH 089/255] =?UTF-8?q?#35=20Feat:=ED=88=AC=ED=91=9C=20?= =?UTF-8?q?=EC=A0=9C=EB=AA=A9=20=EC=84=A4=EC=A0=95=20=EB=B3=B5=EC=88=98=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EC=84=A4=EC=A0=95=20=EA=B8=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=EC=8B=9C=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=B0=A8?= =?UTF-8?q?=EA=B0=90(=EA=B2=BD=EA=B3=84=EA=B0=92=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=95=88=ED=95=B4=EC=A4=8C)=20=ED=88=AC=ED=91=9C=20=EB=A7=88?= =?UTF-8?q?=EA=B0=90=20=EC=84=A4=EC=A0=95=20=ED=85=8C=EA=B7=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=9D=BC=EB=B0=98=EA=B8=80=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 5 +- .../java/friend/spring/domain/Card_poll.java | 11 +++ .../java/friend/spring/domain/Gauge_poll.java | 8 +- .../java/friend/spring/domain/Gauge_vote.java | 2 +- .../friend/spring/domain/General_poll.java | 12 +++ src/main/java/friend/spring/domain/Point.java | 7 ++ src/main/java/friend/spring/domain/Post.java | 14 +--- src/main/java/friend/spring/domain/User.java | 4 + .../friend/spring/domain/enums/PostType.java | 2 +- .../friend/spring/service/PostService.java | 3 + .../spring/service/PostServiceImpl.java | 83 ++++++++++++++++--- .../web/controller/PostRestController.java | 21 ++++- .../friend/spring/web/dto/PostRequestDTO.java | 10 ++- src/main/resources/application.yml | 2 +- 14 files changed, 142 insertions(+), 42 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 7f65647..3b85256 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -27,12 +27,9 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { switch (request.getPostType()){ case 1: - postType=PostType.NOT_VOTE; - break; - case 2: postType=PostType.VOTE; break; - case 3: + case 2: postType=PostType.REVIEW; break; default: diff --git a/src/main/java/friend/spring/domain/Card_poll.java b/src/main/java/friend/spring/domain/Card_poll.java index ba8b090..e302193 100644 --- a/src/main/java/friend/spring/domain/Card_poll.java +++ b/src/main/java/friend/spring/domain/Card_poll.java @@ -18,6 +18,13 @@ public class Card_poll extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(nullable = false, length = 30) + private String pollTitle; + + @Column(nullable = true) + @Builder.Default + private Boolean multipleChoice=true; + @Column(nullable = true) private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. @@ -25,6 +32,7 @@ public class Card_poll extends BaseEntity { private List cardVoteList = new ArrayList<>(); @OneToOne(mappedBy = "cardPoll", cascade = CascadeType.ALL) + @JoinColumn(name = "post_id") private Post post; @OneToMany(mappedBy = "cardPoll",cascade = CascadeType.ALL) @@ -33,4 +41,7 @@ public class Card_poll extends BaseEntity { public void setPost(Post post) { this.post = post; } + public void setMultipleChoice(Boolean multipleChoice){ + this.multipleChoice=multipleChoice; + } } diff --git a/src/main/java/friend/spring/domain/Gauge_poll.java b/src/main/java/friend/spring/domain/Gauge_poll.java index 26e0e8a..4930367 100644 --- a/src/main/java/friend/spring/domain/Gauge_poll.java +++ b/src/main/java/friend/spring/domain/Gauge_poll.java @@ -19,12 +19,10 @@ public class Gauge_poll extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false) - private Integer min=0; - - @Column(nullable = false) - private Integer max=100; + @Column(nullable = false, length = 30) + private String pollTitle; + @Builder.Default @Column(nullable = false) private Integer gauge =0; diff --git a/src/main/java/friend/spring/domain/Gauge_vote.java b/src/main/java/friend/spring/domain/Gauge_vote.java index a6cc42b..f2e3562 100644 --- a/src/main/java/friend/spring/domain/Gauge_vote.java +++ b/src/main/java/friend/spring/domain/Gauge_vote.java @@ -16,7 +16,7 @@ public class Gauge_vote extends BaseEntity { private Long id; @Column(nullable = false) - private Integer value=0; + private Integer value; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") diff --git a/src/main/java/friend/spring/domain/General_poll.java b/src/main/java/friend/spring/domain/General_poll.java index 82219d8..bd5d5dc 100644 --- a/src/main/java/friend/spring/domain/General_poll.java +++ b/src/main/java/friend/spring/domain/General_poll.java @@ -19,6 +19,13 @@ public class General_poll extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(nullable = false, length = 30) + private String pollTitle; + + @Column(nullable = true) + @Builder.Default + private Boolean multipleChoice=true; + @Column(nullable = true) private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. @@ -26,6 +33,7 @@ public class General_poll extends BaseEntity { private List generalVoteList = new ArrayList<>(); @OneToOne(mappedBy = "generalPoll", cascade = CascadeType.ALL) + @JoinColumn(name = "post_id") private Post post; @OneToMany(mappedBy = "generalPoll",cascade = CascadeType.ALL) @@ -35,4 +43,8 @@ public void setPost(Post post) { this.post = post; } + public void setMultipleChoice(Boolean multipleChoice){ + this.multipleChoice=multipleChoice; + } + } diff --git a/src/main/java/friend/spring/domain/Point.java b/src/main/java/friend/spring/domain/Point.java index 88b871a..740f6c9 100644 --- a/src/main/java/friend/spring/domain/Point.java +++ b/src/main/java/friend/spring/domain/Point.java @@ -24,4 +24,11 @@ public class Point extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; + + public void setUser(User user){ + if(this.user != null) + user.getPointList().remove(this); + this.user = user; + user.getPointList().add(this); + } } diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index ce6a8f8..5a9f347 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -41,15 +41,11 @@ public class Post extends BaseEntity { @Enumerated(EnumType.STRING) private PostCategory category; - - @ElementCollection - @Column(nullable = true, length = 100) - private List tag=new ArrayList<>(); - @Enumerated(EnumType.STRING) @Column private PostState state; + @Builder.Default @Column(nullable = false) private Integer view=0; @@ -114,13 +110,7 @@ public void setParentPost(Post parent){ this.parentPost=parent; parent.getReviewPostList().add(this); } - public void setTags(List tags) { - if (tags != null) { - this.tag = new ArrayList<>(tags); - } else { - this.tag.clear(); - } - } + public void setGeneralPoll(General_poll generalPoll) { this.generalPoll = generalPoll; if (generalPoll != null && generalPoll.getPost() != this) { diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index a7f7e7c..130bcb4 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -111,4 +111,8 @@ public class User extends BaseEntity { @Builder.Default @OneToMany(mappedBy = "user") private List cardVoteList = new ArrayList<>(); + + public void setPoint(Integer point) { + this.point = point; + } } diff --git a/src/main/java/friend/spring/domain/enums/PostType.java b/src/main/java/friend/spring/domain/enums/PostType.java index d509e75..f044ef6 100644 --- a/src/main/java/friend/spring/domain/enums/PostType.java +++ b/src/main/java/friend/spring/domain/enums/PostType.java @@ -1,5 +1,5 @@ package friend.spring.domain.enums; public enum PostType { - NOT_VOTE, VOTE, REVIEW + VOTE, REVIEW } diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index 92b7734..623804a 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -2,10 +2,13 @@ import friend.spring.domain.Post; +import friend.spring.domain.User; import friend.spring.web.dto.PostRequestDTO; public interface PostService { void checkPost(Boolean flag); Post joinPost(PostRequestDTO.AddPostDTO request, Long userId); + + Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 5b7ba95..5971f00 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -26,12 +26,21 @@ public class PostServiceImpl implements PostService{ private final CandidateRepository candidateRepository; private final Gauge_PollRepository gaugePollRepository; private final Card_PollRepository cardPollRepository; + private final PointRepository pointRepository; @Override public void checkPost(Boolean flag) { if (!flag) { throw new UserHandler(ErrorStatus.POST_NOT_FOUND); } } + + @Override + public Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user) { + if(request.getPoint()>user.getPoint()){ + return Boolean.FALSE; + } + return Boolean.TRUE; + } @Override @Transactional @@ -42,21 +51,34 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { User user=userRepository.findById(userId) .orElseThrow(()->new RuntimeException("\""+userId+"\"해당 유저가 없습니다")); newPost.setUser(user); - if(request.getTag()!=null){ - newPost.setTags(request.getTag()); - } - -// if(newPost.getPostType()==NOT_VOTE){ -// -// } +//일반 투표 api if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL&&request.getPollOption()!=null){ + //포인트 차감 관련 코드 + if(request.getPoint()!=null) { + if (!checkPoint(request, user)) { + throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); + } + user.setPoint(user.getPoint() - request.getPoint()); + Point newPoint=Point.builder() + .amount(user.getPoint()) + .content("일반 투표에 대한 "+request.getPoint()+" 포인트 차감") + .build(); + newPoint.setUser(user); + pointRepository.save(newPoint); + } + General_poll generalPoll = General_poll.builder() + .pollTitle(request.getPollTitle()) .deadline(request.getDeadline()) .build(); + if(request.getMultipleChoice()!=null){ + generalPoll.setMultipleChoice(request.getMultipleChoice()); + } newPost.setGeneralPoll(generalPoll); generalPollRepository.save(generalPoll); + for (PollOptionDTO option : request.getPollOption()) { Candidate candidate = Candidate.builder() .name(option.getOptionString()) @@ -67,11 +89,33 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { candidateRepository.save(candidate); } } - +//카드 투표 api if(newPost.getPostType()==VOTE&&newPost.getVoteType()==CARD&&request.getPollOption()!=null){ + //포인트 차감 관련 코드 + if(request.getPoint()!=null) { + if (!checkPoint(request, user)) { + throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); + } + user.setPoint(user.getPoint() - request.getPoint()); + Point newPoint=Point.builder() + .amount(user.getPoint()) + .content("일반 투표에 대한 "+request.getPoint()+" 포인트 차감") + .build(); + newPoint.setUser(user); + pointRepository.save(newPoint); + } + + if(!checkPoint(request, user)&&request.getPoint()!=null){ + throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); + } + Card_poll cardPoll = Card_poll.builder() + .pollTitle(request.getPollTitle()) .deadline(request.getDeadline()) .build(); + if(request.getMultipleChoice()!=null){ + cardPoll.setMultipleChoice(request.getMultipleChoice()); + } newPost.setCardPoll(cardPoll); cardPollRepository.save(cardPoll); @@ -85,11 +129,28 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { candidateRepository.save(candidate); } } +//게이지 투표 api + if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GAUGE){ + //포인트 차감 관련 코드 + if(request.getPoint()!=null) { + if (!checkPoint(request, user)) { + throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); + } + user.setPoint(user.getPoint() - request.getPoint()); + Point newPoint=Point.builder() + .amount(user.getPoint()) + .content("일반 투표에 대한 "+request.getPoint()+" 포인트 차감") + .build(); + newPoint.setUser(user); + pointRepository.save(newPoint); + } + + if(!checkPoint(request, user)&&request.getPoint()!=null){ + throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); + } - if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GAUGE&&request.getPollOption()!=null){ Gauge_poll gaugePoll = Gauge_poll.builder() - .max(100) - .min(0) + .pollTitle(request.getPollTitle()) .gauge(0) .deadline(request.getDeadline()) .build(); diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index f6ab7e5..5466826 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -6,6 +6,8 @@ import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -18,9 +20,22 @@ public class PostRestController { private final PostService postService; @PostMapping("/{user-id}") - @Operation(summary = "글 작성 API", description = "PostType = 1 : NOT_VOTE, 2 : VOTE, 3 : REVIEW
" + - "Category = 1 : EDUCATION, 2 : ENTERTAINMENT, 3 : LIFESTYLE, 4 : ECONOMY, 5 : SHOPPING, 6 : OTHERS
" + - "postVoteType = 1 : GENERAL, 2 : GAUGE, 3 : CARD") + @Operation(summary = "글 작성 API", description = "글을 추가 합니다.") + @Parameters({ + @Parameter(name="title", description=" 글 제목"), + @Parameter(name="content", description=" 글 내용"), + @Parameter(name="category", description=" 카테고리
1 : EDUCATION
2 : ENTERTAINMENT
3 : LIFESTYLE
4 : ECONOMY
5 : SHOPPING" + + "
6 : OTHERS" ), + @Parameter(name="postType", description=" 글 종류
1 : NOT_VOTE
2 : VOTE
3 : REVIEW"), + @Parameter(name="postVoteType", description=" 투표 종류
1 : GENERAL
2 : GAUGE
3 : CARD
해당 사항 없을시 null"), + @Parameter(name="pollTitle", description=" 투표 제목"), + @Parameter(name="multipleChoice", description=" 복수 선택 여부"), + @Parameter(name="pollOption", description=" 투표 후보{optionString : string, optionImg : string}
해당 사항 없을시 null"), + @Parameter(name="parent_id", description=" 원글(후기글 경우) id
해당 사항 없을시 null"), + @Parameter(name="deadline", description=" 투표 마감 시간
해당 사항 없을시 null"), + @Parameter(name="point", description=" 포인트
해당 사항 없을시 null") + + }) public ApiResponse join(@RequestBody @Valid PostRequestDTO.AddPostDTO request, @PathVariable(name="user-id")Long UserId){ Post post= postService.joinPost(request,UserId); diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index a37f384..8a05a1e 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -16,13 +16,15 @@ public static class AddPostDTO{ String title; @NotBlank String content; - @NotBlank - Integer postType; // 1: not vote, 2: vote, 3: review Integer category; //미정 + @NotBlank + Integer postType; // 1: vote, 2: review Integer postVoteType;// 1: general, 2: gauge - Long parent_id; + String pollTitle; + Boolean multipleChoice; List pollOption; - List tag; + Long parent_id; + @NotBlank Timestamp deadline; Integer point; } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index d8ad835..fc07363 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -15,6 +15,6 @@ spring: format_sql: true use_sql_comments: true hbm2ddl: - auto: create + auto: update default_batch_fetch_size: 1000 globally_quoted_identifiers: true \ No newline at end of file From ea0c3b909ef71b49eaf66878e0194d51241d1c8c Mon Sep 17 00:00:00 2001 From: hjh Date: Thu, 1 Feb 2024 17:52:14 +0900 Subject: [PATCH 090/255] =?UTF-8?q?#35=20Feat:=ED=88=AC=ED=91=9C=20?= =?UTF-8?q?=EC=A0=9C=EB=AA=A9=20=EC=84=A4=EC=A0=95=20=EB=B3=B5=EC=88=98=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EC=84=A4=EC=A0=95=20=EA=B8=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=EC=8B=9C=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=B0=A8?= =?UTF-8?q?=EA=B0=90(=EA=B2=BD=EA=B3=84=EA=B0=92=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=95=88=ED=95=B4=EC=A4=8C)=20=ED=88=AC=ED=91=9C=20=EB=A7=88?= =?UTF-8?q?=EA=B0=90=20=EC=84=A4=EC=A0=95=20=ED=85=8C=EA=B7=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=9D=BC=EB=B0=98=EA=B8=80=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/repository/PointRepository.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/friend/spring/repository/PointRepository.java diff --git a/src/main/java/friend/spring/repository/PointRepository.java b/src/main/java/friend/spring/repository/PointRepository.java new file mode 100644 index 0000000..8e4fd90 --- /dev/null +++ b/src/main/java/friend/spring/repository/PointRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.Point; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PointRepository extends JpaRepository { +} From 83d683be88c798f53d15146cd7a66730283dcad9 Mon Sep 17 00:00:00 2001 From: hjh Date: Thu, 1 Feb 2024 18:11:36 +0900 Subject: [PATCH 091/255] =?UTF-8?q?#35=20Feat:=ED=88=AC=ED=91=9C=20?= =?UTF-8?q?=EC=A0=9C=EB=AA=A9=20=EC=84=A4=EC=A0=95=20=EB=B3=B5=EC=88=98=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EC=84=A4=EC=A0=95=20=EA=B8=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=EC=8B=9C=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=B0=A8?= =?UTF-8?q?=EA=B0=90(=EA=B2=BD=EA=B3=84=EA=B0=92=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=95=88=ED=95=B4=EC=A4=8C)=20=EA=B8=80=20=ED=88=AC=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=ED=9A=8D=EB=93=9D=20?= =?UTF-8?q?=ED=88=AC=ED=91=9C=20=EB=A7=88=EA=B0=90=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=ED=85=8C=EA=B7=B8=20=EC=82=AD=EC=A0=9C=20=EC=9D=BC=EB=B0=98?= =?UTF-8?q?=EA=B8=80=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/service/PostServiceImpl.java | 6 ++--- .../spring/service/VoteServiceImpl.java | 26 +++++++++++++++++++ .../web/controller/VoteRestController.java | 14 ++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 5971f00..82a00dc 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -62,7 +62,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { user.setPoint(user.getPoint() - request.getPoint()); Point newPoint=Point.builder() .amount(user.getPoint()) - .content("일반 투표에 대한 "+request.getPoint()+" 포인트 차감") + .content("일반 투표 작성에 대한 "+request.getPoint()+" 포인트 차감") .build(); newPoint.setUser(user); pointRepository.save(newPoint); @@ -99,7 +99,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { user.setPoint(user.getPoint() - request.getPoint()); Point newPoint=Point.builder() .amount(user.getPoint()) - .content("일반 투표에 대한 "+request.getPoint()+" 포인트 차감") + .content("게이지 투표 등록에 대한 "+request.getPoint()+" 포인트 차감") .build(); newPoint.setUser(user); pointRepository.save(newPoint); @@ -139,7 +139,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { user.setPoint(user.getPoint() - request.getPoint()); Point newPoint=Point.builder() .amount(user.getPoint()) - .content("일반 투표에 대한 "+request.getPoint()+" 포인트 차감") + .content("카드 투표 등록에 대한 "+request.getPoint()+" 포인트 차감") .build(); newPoint.setUser(user); pointRepository.save(newPoint); diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index 8a9a50d..ba0bed1 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -19,6 +19,7 @@ public class VoteServiceImpl implements VoteService{ private final Gauge_VoteRepository gaugeVoteRepository; private final Card_VoteRepository cardVoteRepository; private final PostRepository postRepository; + private final PointRepository pointRepository; @Override @Transactional public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId) { @@ -46,6 +47,15 @@ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request if (request.getSelectList() != null) { newGeneralVote.setSelect_list(request.getSelectList()); } + + user.setPoint(user.getPoint() + 5); + Point newPoint=Point.builder() + .amount(user.getPoint()) + .content("일반 투표에 대한 "+5+" 포인트 획득") + .build(); + newPoint.setUser(user); + pointRepository.save(newPoint); + return generalVoteRepository.save(newGeneralVote); } @@ -63,6 +73,14 @@ public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long Gauge_poll gaugePoll=post.getGaugePoll(); newGaugeVote.setGaugePoll(gaugePoll); + user.setPoint(user.getPoint() + 5); + Point newPoint=Point.builder() + .amount(user.getPoint()) + .content("게이지 투표에 대한 "+5+" 포인트 획득") + .build(); + newPoint.setUser(user); + pointRepository.save(newPoint); + return gaugeVoteRepository.save(newGaugeVote); } @Override @@ -92,6 +110,14 @@ public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request, Long us if (request.getSelectList() != null) { newCardVote.setSelect_list(request.getSelectList()); } + user.setPoint(user.getPoint() + 5); + Point newPoint=Point.builder() + .amount(user.getPoint()) + .content("카드 투표에 대한 "+5+" 포인트 획득") + .build(); + newPoint.setUser(user); + pointRepository.save(newPoint); + return cardVoteRepository.save(newCardVote); } diff --git a/src/main/java/friend/spring/web/controller/VoteRestController.java b/src/main/java/friend/spring/web/controller/VoteRestController.java index 7492bd3..7de47dc 100644 --- a/src/main/java/friend/spring/web/controller/VoteRestController.java +++ b/src/main/java/friend/spring/web/controller/VoteRestController.java @@ -9,6 +9,8 @@ import friend.spring.web.dto.VoteRequestDTO; import friend.spring.web.dto.VoteResponseDTO; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -23,6 +25,10 @@ public class VoteRestController { private final VoteService voteService; @PostMapping("/{post-id}/{user-id}/generalVote") @Operation(summary = "일반 투표 API", description = "임시로 user-id 입력") + @Parameters({ + @Parameter(name="postId", description=" 글 id"), + @Parameter(name="selectList", description=" 투표 후보 id 리스트") + }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GeneralVoteRequestDTO request, @PathVariable(name="user-id")Long UserId){ General_vote generalVote= voteService.castGeneralVote(request,UserId); @@ -31,6 +37,10 @@ public ApiResponse join(@RequestBody @Va @PostMapping("/{post-id}/{user-id}/gaugeVote") @Operation(summary = "게이지 투표 API", description = "임시로 user-id 입력") + @Parameters({ + @Parameter(name="postId", description=" 글 id"), + @Parameter(name="selectList", description=" 게이지") + }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GaugeVoteRequestDTO request, @PathVariable(name="user-id")Long UserId){ Gauge_vote gaugeVote= voteService.castGaugeVote(request,UserId); @@ -39,6 +49,10 @@ public ApiResponse join(@RequestBody @Vali @PostMapping("/{post-id}/{user-id}/cardVote") @Operation(summary = "카드 투표 API", description = "임시로 user-id 입력") + @Parameters({ + @Parameter(name="postId", description=" 글 id"), + @Parameter(name="selectList", description=" 투표 후보 id 리스트") + }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.CardVoteRequestDTO request, @PathVariable(name="user-id")Long UserId){ Card_vote cardVote= voteService.castCardVote(request,UserId); From c1e4c2da0d29901076d40b0ca47d5116099036e7 Mon Sep 17 00:00:00 2001 From: hjh Date: Thu, 1 Feb 2024 19:56:24 +0900 Subject: [PATCH 092/255] =?UTF-8?q?#44=20Feat:=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/converter/UserConverter.java | 7 +++++++ src/main/java/friend/spring/service/UserService.java | 2 ++ .../java/friend/spring/service/UserServiceImpl.java | 7 +++++++ .../spring/web/controller/UserRestController.java | 10 ++++++++++ .../java/friend/spring/web/dto/UserResponseDTO.java | 9 +++++++++ 5 files changed, 35 insertions(+) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 86f1a40..4062ede 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -2,6 +2,7 @@ import friend.spring.domain.User; import friend.spring.web.dto.UserResponseDTO; +import io.swagger.models.auth.In; public class UserConverter { public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ @@ -15,4 +16,10 @@ public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ .build(); } + public static UserResponseDTO.PointViewDTO toPointViewResDTO(Integer point){ + return UserResponseDTO.PointViewDTO.builder() + .point(point) + .build(); + } + } diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index 5f31113..ba1bbb4 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -7,4 +7,6 @@ public interface UserService { User findMyPage(Long id); void checkUser(Boolean flag); + + Integer pointCheck(Long id); } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index a38b5fa..6e26ab1 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -33,4 +33,11 @@ public void checkUser(Boolean flag) { throw new UserHandler(ErrorStatus.USER_NOT_FOUND); } } + + @Override + public Integer pointCheck(Long id) { + User user=userRepository.findById(id) + .orElseThrow(()->new RuntimeException("\""+id+"\"해당 유저가 없습니다")); + return user.getPoint(); + } } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 944426c..db8c81a 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -6,6 +6,9 @@ import friend.spring.domain.User; import friend.spring.service.UserService; import friend.spring.web.dto.UserResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestHeader; @@ -26,4 +29,11 @@ public ApiResponse myPage(@RequestHeader(name = "i User Page = userService.findMyPage(userId); return ApiResponse.onSuccess(UserConverter.toMypageResDTO(Page)); } + + @GetMapping("/point") + @Operation(summary = "포인트 조회 API", description = "임시로 user-id 입력") + public ApiResponse myPoint(@RequestHeader(name = "id") Long userId) { + Integer point = userService.pointCheck(userId); + return ApiResponse.onSuccess(UserConverter.toPointViewResDTO(point)); + } } diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index 34880c0..364f792 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -20,4 +20,13 @@ public static class MyPageResDTO { Integer userRecommend; } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class PointViewDTO { + Integer point; + } + + } From ca0af91f3e9e978b52e7cd2c869835d6f939a760 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Thu, 1 Feb 2024 19:59:10 +0900 Subject: [PATCH 093/255] =?UTF-8?q?#42=20docs=20:=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80(Q&A=EC=A7=88=EB=AC=B8,=20Q&A?= =?UTF-8?q?=EB=8B=B5=EB=B3=80)=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/CommentConverter.java | 10 +++ .../spring/converter/PostConverter.java | 11 +++ .../spring/converter/UserConverter.java | 80 ++++++++++++++++++- .../spring/repository/CommentRepository.java | 5 ++ .../spring/repository/LevelRepository.java | 9 +++ .../spring/repository/PostRepository.java | 4 + .../friend/spring/service/CommentService.java | 3 + .../spring/service/CommentServiceImpl.java | 13 +++ .../friend/spring/service/PostService.java | 2 + .../spring/service/PostServiceImpl.java | 18 +++++ .../friend/spring/service/UserService.java | 2 + .../spring/service/UserServiceImpl.java | 15 ++++ .../web/controller/UserRestController.java | 36 ++++++++- .../spring/web/dto/CommentResponseDTO.java | 11 +++ .../spring/web/dto/PostResponseDTO.java | 17 +++- .../spring/web/dto/UserResponseDTO.java | 36 +++++++++ 16 files changed, 263 insertions(+), 9 deletions(-) create mode 100644 src/main/java/friend/spring/repository/LevelRepository.java diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index f114008..efef77e 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -81,4 +81,14 @@ public static CommentResponseDTO.commentSelectRes toCommentSelectRes(Comment_cho .point(comment_choice.getPoint()) .build(); } + public static CommentResponseDTO.myCommentRes toMyCommentResDTO(Comment comment){ + return CommentResponseDTO.myCommentRes.builder() + .nickName(comment.getUser().getNickname()) + .createdAt(comment.getCreatedAt()) + .content(comment.getContent()) + .commentLike(comment.getCommentLikeList().size()) + .reComment(comment.getSubCommentList().size()) + .build(); + } + } diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 7f65647..3a19bf9 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -90,6 +90,17 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { .state(PostState.POSTING) .build(); } + + public static PostResponseDTO.MyPostDTO toMyPostResDTO(Post post){ + return PostResponseDTO.MyPostDTO.builder() + .nickName(post.getUser().getNickname()) + .createdAt(post.getCreatedAt()) + .title(post.getTitle()) + .postLike(post.getPostLikeList().size()) + .comment(post.getCommentList().size()) + .build(); + } + } diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 7fc2d4d..d945bae 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -1,13 +1,22 @@ package friend.spring.converter; +import friend.spring.domain.Comment; +import friend.spring.domain.Level; +import friend.spring.domain.Post; import friend.spring.domain.User; +import friend.spring.web.dto.CommentResponseDTO; +import friend.spring.web.dto.PostResponseDTO; import friend.spring.web.dto.UserResponseDTO; +import org.springframework.data.domain.Page; + +import java.util.List; +import java.util.stream.Collectors; public class UserConverter { public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ return UserResponseDTO.MyPageResDTO.builder() .userPhoto(user.getImage()) - .userName(user.getName()) + .userName(user.getNickname()) .userPoint(user.getPoint()) .userLevelInt(user.getLevel().getLike()) .userLevelName(user.getLevel().getName()) @@ -21,4 +30,73 @@ public static UserResponseDTO.EmailSendRes toEmailSendRes(String code) { .code(code) .build(); } + //나의 프로필(Q&A질문) + public static UserResponseDTO.QuestionResDTO toQuestionResDTO(User user, Level nxtLevel, Page postList, Page commentList){ + //질문 목록 + List myPostDTOList = postList.stream() + .map(PostConverter::toMyPostResDTO).collect(Collectors.toList()); + + //총 답변수 + int all = commentList.getSize(); + //채택 답변수 + List myCommentList = commentList.stream() + .filter(comment -> comment.getCommentChoiceList().isEmpty()).collect(Collectors.toList()); + //답변 채택률 + int aChoice = all - myCommentList.size(); + double aChoicePercent = ((double)aChoice / (double)all) * 100; + + //질문 채택률 + int Question = myPostDTOList.size(); + List myPostList = postList.stream() + .filter(post -> post.getCommentChoiceList().isEmpty()).collect(Collectors.toList()); + double pChoicePercent = ((double) (Question - myPostList.size()) / (double) Question)*100; + + //남은 다음 등급 + double nxtGrade = ((double)user.getLike()/(double)(nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; + return UserResponseDTO.QuestionResDTO.builder() + .userPhoto(user.getImage()) + .nickName(user.getNickname()) + .recommend(user.getLike()) + .grade(user.getLevel().getName()) + .nextGrade(nxtGrade) + .nextGradeName(nxtLevel.getName()) + .adoptComments(aChoice) + .adoptCommentPercent(aChoicePercent) + .postNum(myPostDTOList.size()) + .adoptPostPercent(pChoicePercent) + .postList(myPostDTOList) + .build(); + } + + //나의 프로필(Q&A답변) + public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLevel, Page commentList){ + //답변 목록 + List myCommentDTOList = commentList.stream() + .map(CommentConverter::toMyCommentResDTO).collect(Collectors.toList()); + //총 답변수 + int all = myCommentDTOList.size(); + + //채택 답변수 + List myCommentList = commentList.stream() + .filter(comment -> comment.getCommentChoiceList().isEmpty()).collect(Collectors.toList()); + int choice = all - myCommentList.size(); + //채택 답변률 + double percent = ((double)choice / (double)all) * 100.0; + + //남은 다음 등급 + double nxtGrade = ((double)user.getLike()/(double)(nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; + return UserResponseDTO.AnswerResDTO.builder() + .userPhoto(user.getName()) + .nickName(user.getNickname()) + .recommend(user.getLike()) + .grade(user.getLevel().getName()) + .nextGrade(nxtGrade) + .nextGradeName(nxtLevel.getName()) + .adoptComments(choice) + .adoptCommentPercent(percent) + .commentList(myCommentDTOList) + .build(); + } + + } diff --git a/src/main/java/friend/spring/repository/CommentRepository.java b/src/main/java/friend/spring/repository/CommentRepository.java index 6292aad..737bc18 100644 --- a/src/main/java/friend/spring/repository/CommentRepository.java +++ b/src/main/java/friend/spring/repository/CommentRepository.java @@ -1,7 +1,9 @@ package friend.spring.repository; import friend.spring.domain.Comment; +import friend.spring.domain.User; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -9,4 +11,7 @@ public interface CommentRepository extends JpaRepository { Page findByPostIdAndParentCommentIsNull(Long postId, Pageable pageable); + + Page findAllByUser(User user, PageRequest pageRequest); + } diff --git a/src/main/java/friend/spring/repository/LevelRepository.java b/src/main/java/friend/spring/repository/LevelRepository.java new file mode 100644 index 0000000..fed06c6 --- /dev/null +++ b/src/main/java/friend/spring/repository/LevelRepository.java @@ -0,0 +1,9 @@ +package friend.spring.repository; + +import friend.spring.domain.Level; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface LevelRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index f62091e..653b244 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -1,7 +1,11 @@ package friend.spring.repository; import friend.spring.domain.Post; +import friend.spring.domain.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; public interface PostRepository extends JpaRepository { + Page findAllByUser(User user, PageRequest pageRequest); } diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index 1fc6008..59a5e05 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -27,4 +27,7 @@ public interface CommentService { Comment_choice selectComment(Long postId, Long commentId, Long userId); void editComment(Long postId, Long commentId, CommentRequestDTO.commentEditReq request, Long userId); + + Page getMyCommentList(Long userId, Integer page); + } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index c60e087..4c4add7 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -230,4 +230,17 @@ public void editComment(Long postId, Long commentId, CommentRequestDTO.commentEd } comment.update(request.getContent()); } + + //한 유저의 모든 댓글 + @Override + public Page getMyCommentList(Long userId, Integer page) { + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()){ + userService.checkUser(false); + } + User user = optionalUser.get(); + Page userPage = commentRepository.findAllByUser(user, PageRequest.of(page, 5)); + return userPage; + } } + diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index e5dfd42..c7802bd 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -3,6 +3,7 @@ import friend.spring.domain.Post; import friend.spring.web.dto.PostRequestDTO; +import org.springframework.data.domain.Page; public interface PostService { void checkPost(Boolean flag); @@ -11,5 +12,6 @@ public interface PostService { Post joinPost(PostRequestDTO.AddPostDTO request, Long userId); + Page getMyPostList(Long userId, Integer page); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index bde8cd4..8337620 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -10,9 +10,13 @@ import friend.spring.web.dto.PollOptionDTO; import friend.spring.web.dto.PostRequestDTO; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Optional; + import static friend.spring.domain.enums.PostType.*; import static friend.spring.domain.enums.PostVoteType.*; @@ -115,4 +119,18 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { return postRepository.save(newPost); } + + //한 유저의 모든 질문글 + @Override + public Page getMyPostList(Long userId, Integer page) { + Optional user = userRepository.findById(userId); + if(user.isEmpty()){ + throw new UserHandler(ErrorStatus.USER_NOT_FOUND); + } + + User myUser = user.get(); + + Page userPage = postRepository.findAllByUser(myUser, PageRequest.of(page, 5)); + return userPage; + } } diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index 5f31113..a784c8a 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -1,5 +1,6 @@ package friend.spring.service; +import friend.spring.domain.Level; import friend.spring.domain.User; import java.util.Optional; @@ -7,4 +8,5 @@ public interface UserService { User findMyPage(Long id); void checkUser(Boolean flag); + Level nextLevel(Long id); } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 182fca8..6a698a5 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -1,7 +1,10 @@ package friend.spring.service; +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.domain.Level; import friend.spring.domain.User; +import friend.spring.repository.LevelRepository; import friend.spring.repository.UserRepository; import friend.spring.apiPayload.handler.UserHandler; import lombok.RequiredArgsConstructor; @@ -19,6 +22,7 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; + private final LevelRepository levelRepository; @Override public User findMyPage(Long id) { @@ -35,5 +39,16 @@ public void checkUser(Boolean flag) { throw new UserHandler(USER_NOT_FOUND); } } + @Override + public Level nextLevel(Long id) { + Optional user = userRepository.findById(id); + if(user.isEmpty()) { + throw new UserHandler(USER_NOT_FOUND); + } + Long curId = user.get().getLevel().getId(); + Long nxtId = curId + 1; + Level nxtLevel = levelRepository.findById(nxtId).get(); + return nxtLevel; + } } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 4722eac..37f3691 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -2,13 +2,19 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.UserConverter; +import friend.spring.domain.Comment; +import friend.spring.domain.Level; +import friend.spring.domain.Post; import friend.spring.domain.User; +import friend.spring.service.CommentService; import friend.spring.service.EmailService; +import friend.spring.service.PostService; import friend.spring.service.UserService; import friend.spring.web.dto.UserRequestDTO; import friend.spring.web.dto.UserResponseDTO; import io.swagger.annotations.Api; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; @@ -21,11 +27,13 @@ public class UserRestController { private final UserService userService; private final EmailService mailService; - + private final PostService postService; + private final CommentService commentService; @GetMapping("/my-page") - public ApiResponse myPage(@RequestHeader(name = "id") Long userId) { - User Page = userService.findMyPage(userId); - return ApiResponse.onSuccess(UserConverter.toMypageResDTO(Page)); + public ApiResponse getMyPage( + @RequestHeader(name = "id") Long userId) { + User myPage = userService.findMyPage(userId); + return ApiResponse.onSuccess(UserConverter.toMypageResDTO(myPage)); } @PostMapping ("/mailSend")//이메일 인증 코드 전송 @@ -41,6 +49,26 @@ public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailS mailService.CheckAuthNum(emailSendCheckReq.getEmail(), emailSendCheckReq.getAuthNum()); return ApiResponse.onSuccess(null); + } + @GetMapping("/my-page/profile/question") + public ApiResponse getQuestion( + @RequestHeader(name = "id") Long userId, + @RequestParam(name = "page") Integer page){ + User myPage = userService.findMyPage(userId); + Level nxtLevel = userService.nextLevel(userId); + Page myPostList = postService.getMyPostList(userId, page); + Page myCommentList = commentService.getMyCommentList(userId, page); + return ApiResponse.onSuccess(UserConverter.toQuestionResDTO(myPage, nxtLevel, myPostList, myCommentList)); + } + @GetMapping("/my-page/profile/answer") + public ApiResponse getAnswer( + @RequestHeader(name = "id") Long userId, + @RequestParam(name = "page") Integer page){ + User myPage = userService.findMyPage(userId); + Level nxtLevel = userService.nextLevel(userId); + Page myCommentList = commentService.getMyCommentList(userId, page); + return ApiResponse.onSuccess(UserConverter.toAnswerResDTO(myPage, nxtLevel, myCommentList)); } } + diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index f43517d..1c7d760 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -51,4 +51,15 @@ public static class commentSelectRes { Long commentChoiceId; Integer point; } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class myCommentRes { + String nickName; + LocalDateTime createdAt; + String content; + Integer commentLike; + Integer reComment; + } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 8faf54e..761e077 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -1,8 +1,5 @@ package friend.spring.web.dto; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; import java.time.LocalDateTime; public class PostResponseDTO { @@ -14,4 +11,16 @@ public static class AddPostResultDTO { Long postId; LocalDateTime createdAt; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class MyPostDTO { + String nickName; + LocalDateTime createdAt; + String title; + Integer postLike; + Integer comment; + } } \ No newline at end of file diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index 58a462e..a8cd200 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -6,6 +6,7 @@ import javax.validation.constraints.Email; import javax.validation.constraints.NotEmpty; +import java.util.List; public class UserResponseDTO { @@ -62,4 +63,39 @@ public static class EmailSendRes { private String code; } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class QuestionResDTO { + String userPhoto; + String nickName; + Integer recommend; + String grade; + Double nextGrade; + String nextGradeName; + Integer adoptComments; + Double adoptCommentPercent; + Integer postNum; + Double adoptPostPercent; + List postList; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class AnswerResDTO { + String userPhoto; + String nickName; + Integer recommend; + String grade; + Double nextGrade; + String nextGradeName; + Integer adoptComments; + Double adoptCommentPercent; + List commentList; + } + + } \ No newline at end of file From 72755ed953ecdea605a62f74b83294a8bf6bcfee Mon Sep 17 00:00:00 2001 From: park sang woo Date: Fri, 2 Feb 2024 00:48:00 +0900 Subject: [PATCH 094/255] =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/UserConverter.java | 50 ++++++++++++++++++- src/main/java/friend/spring/domain/User.java | 8 +-- .../spring/repository/UserRepository.java | 3 ++ .../friend/spring/service/UserService.java | 5 +- .../spring/service/UserServiceImpl.java | 15 +++++- .../web/controller/UserRestController.java | 10 ++++ .../friend/spring/web/dto/UserRequestDTO.java | 29 +++++++---- .../spring/web/dto/UserResponseDTO.java | 46 +++++++---------- 8 files changed, 122 insertions(+), 44 deletions(-) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 7fc2d4d..3242d6f 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -1,13 +1,21 @@ package friend.spring.converter; import friend.spring.domain.User; +import friend.spring.domain.enums.Gender; +import friend.spring.web.dto.UserRequestDTO; import friend.spring.web.dto.UserResponseDTO; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +import java.time.LocalDate; +import java.time.LocalDateTime; public class UserConverter { + + public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ return UserResponseDTO.MyPageResDTO.builder() .userPhoto(user.getImage()) - .userName(user.getName()) + .userName(user.getNickname()) .userPoint(user.getPoint()) .userLevelInt(user.getLevel().getLike()) .userLevelName(user.getLevel().getName()) @@ -21,4 +29,44 @@ public static UserResponseDTO.EmailSendRes toEmailSendRes(String code) { .code(code) .build(); } + + public static UserResponseDTO.JoinResultDTO joinResultDTO(User user){ + return UserResponseDTO.JoinResultDTO.builder() + .email(user.getEmail()) + .createAt(LocalDate.from(LocalDateTime.now())) + .build(); + + } + public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest){ + + Gender gender = null; + + switch (userJoinRequest.getGender()){ + case 1: + gender = Gender.MALE; + break; + case 2: + gender = Gender.FEMALE; + break; + case 3: + gender = Gender.NONE; + break; + } + return User.builder() + .email(userJoinRequest.getEmail()) + .password(userJoinRequest.getPassword()) + .nickname(userJoinRequest.getNickname()) + .gender(gender) + .phone(userJoinRequest.getPhone()) + .agree_info(userJoinRequest.isAgree_info()) + .agree_marketing(userJoinRequest.isAgree_marketing()) + .birth(userJoinRequest.getBirth()) + .name(userJoinRequest.getName()) + .kakao(userJoinRequest.getKakao()) + .image(userJoinRequest.getImage()) + .is_deleted(userJoinRequest.is_deleted()) + .point(userJoinRequest.getPoint()) + .like(userJoinRequest.getLike()) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index e4acd9e..e4184bb 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -36,7 +36,7 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = false, length = 50) private String email; - @Column(nullable = false, length = 15) + @Column(nullable = false, length = 15) //name 넣고 돌리면 name칸 비어잇어서 안되고, 없애면 오류 확인 private String name; @Pattern(regexp = "^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$", message = "전화번호 형식이 맞지 않습니다.") @@ -44,7 +44,7 @@ public class User extends BaseEntity implements UserDetails { private String phone; @Enumerated(EnumType.STRING) - @Column + @Column(columnDefinition = "VARCHAR(10)") private Gender gender; @Column(nullable = false, length = 30) @@ -63,7 +63,7 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true) private String image; - @Column(nullable = false) + @Column(nullable = true)//잠시 true로 수정 private Boolean is_deleted; @Column(nullable = true) @@ -72,7 +72,7 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true) private String kakao; - @Column(nullable = false) + @Column(nullable = true)//잠시 true private Integer like; diff --git a/src/main/java/friend/spring/repository/UserRepository.java b/src/main/java/friend/spring/repository/UserRepository.java index 370db18..ac0ca2d 100644 --- a/src/main/java/friend/spring/repository/UserRepository.java +++ b/src/main/java/friend/spring/repository/UserRepository.java @@ -11,4 +11,7 @@ public interface UserRepository extends JpaRepository { Optional findByEmail(String email); Optional findByNickname(String nickname); + + Boolean existsByEmail(String email); + Boolean existsByNickname(String nickname); } diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index 5f31113..3a3cc37 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -1,10 +1,13 @@ package friend.spring.service; import friend.spring.domain.User; +import friend.spring.web.dto.UserRequestDTO; -import java.util.Optional; public interface UserService { + + User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest); + User findMyPage(Long id); void checkUser(Boolean flag); } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 182fca8..c1f77e5 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -1,13 +1,17 @@ package friend.spring.service; +import friend.spring.converter.UserConverter; import friend.spring.domain.User; import friend.spring.repository.UserRepository; import friend.spring.apiPayload.handler.UserHandler; +import friend.spring.web.dto.UserRequestDTO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; + import java.util.Optional; import static friend.spring.apiPayload.code.status.ErrorStatus.*; @@ -19,11 +23,12 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; + //private final BCryptPasswordEncoder bCryptPasswordEncoder; @Override public User findMyPage(Long id) { Optional user = userRepository.findById(id); - if(user.isEmpty()){ + if (user.isEmpty()) { throw new UserHandler(USER_NOT_FOUND); } return user.get(); @@ -35,5 +40,13 @@ public void checkUser(Boolean flag) { throw new UserHandler(USER_NOT_FOUND); } } + public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest){ + + User newUser = UserConverter.toUser(userJoinRequest); + + return userRepository.saveAndFlush(newUser); + } } + + diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 4722eac..87a7607 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -3,8 +3,10 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.UserConverter; import friend.spring.domain.User; +import friend.spring.repository.UserRepository; import friend.spring.service.EmailService; import friend.spring.service.UserService; +import friend.spring.service.UserServiceImpl; import friend.spring.web.dto.UserRequestDTO; import friend.spring.web.dto.UserResponseDTO; import io.swagger.annotations.Api; @@ -20,6 +22,7 @@ public class UserRestController { private final UserService userService; + private final UserRepository userRepository; private final EmailService mailService; @GetMapping("/my-page") @@ -42,5 +45,12 @@ public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailS mailService.CheckAuthNum(emailSendCheckReq.getEmail(), emailSendCheckReq.getAuthNum()); return ApiResponse.onSuccess(null); + } + @PostMapping("/join")//회원가입 + public ApiResponse join(@RequestBody @Valid UserRequestDTO.UserJoinRequest userJoinRequest) { + + User user = userService.joinUser(userJoinRequest); + return ApiResponse.onSuccess(UserConverter.joinResultDTO(user)); + } } diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 11b9ebf..25b3636 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -1,6 +1,7 @@ package friend.spring.web.dto; import friend.spring.domain.enums.Gender; +import io.swagger.models.auth.In; import lombok.Getter; import lombok.AllArgsConstructor; @@ -17,15 +18,22 @@ public class UserRequestDTO { @AllArgsConstructor @Getter @Setter - public static class UserJoinRequest{// - private String email; - private String password; - private String nickname; + public static class UserJoinRequest { - private Gender gender; - private boolean agree_info; - private boolean agree_marketing; - private LocalDate birth; + String email; + String password; + String nickname; + String phone; + Integer gender; + boolean agree_info; + boolean agree_marketing; + LocalDate birth; + String name; + boolean is_deleted; + String image; + Integer point; + String kakao; + Integer like; } @@ -33,7 +41,7 @@ public static class UserJoinRequest{// @AllArgsConstructor @Getter @Setter - public static class UserLoginRequest{//로그인 요청 + public static class UserLoginRequest {//로그인 요청 String email; String password; } @@ -57,7 +65,7 @@ public static class EmailCheckReq { @AllArgsConstructor @Getter @Setter - public static class NicknameCheckReq{ + public static class NicknameCheckReq { private String nickname; } @@ -79,6 +87,7 @@ public static class EmailSendReq { @NotEmpty(message = "이메일을 입력해 주세요") private String email; } + @NoArgsConstructor @AllArgsConstructor @Getter diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index 58a462e..a7b3dd8 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -6,6 +6,7 @@ import javax.validation.constraints.Email; import javax.validation.constraints.NotEmpty; +import java.time.LocalDate; public class UserResponseDTO { @@ -20,40 +21,31 @@ public static class MyPageResDTO { Integer userLevelInt; String userLevelName; Integer userRecommend; + } - public static class EmailDTO { - @NoArgsConstructor - @AllArgsConstructor - @Getter - @Setter - public static class Email { - Long id; - String code; - Boolean isCorrected; - Boolean ExistEmail; - } + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Builder + public static class JoinResultDTO { - @NoArgsConstructor - @AllArgsConstructor - @Getter - @Setter - public static class UserJoinRes { - private User user; - } + String email; + LocalDate createAt; + } - @NoArgsConstructor - @AllArgsConstructor - @Getter - @Setter - public static class UserInfo { - private String email; - private String nickname; - private Gender gender; + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Builder + public static class UserInfo { + private String email; + private String nickname; + private Gender gender; - } } + @Builder @Getter @NoArgsConstructor From 006cfa13846ec309d3ff485a1d5872d720355e46 Mon Sep 17 00:00:00 2001 From: hjh Date: Fri, 2 Feb 2024 02:52:08 +0900 Subject: [PATCH 095/255] =?UTF-8?q?#48=20Feat:=EA=B8=80=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 74 +++++++++++++++++++ src/main/java/friend/spring/domain/Post.java | 4 + .../spring/service/PostQueryService.java | 9 +++ .../spring/service/PostQueryServiceImpl.java | 27 +++++++ .../web/controller/PostRestController.java | 17 +++++ .../friend/spring/web/dto/PollOptionDTO.java | 6 +- .../spring/web/dto/PostResponseDTO.java | 25 +++++++ 7 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 src/main/java/friend/spring/service/PostQueryService.java create mode 100644 src/main/java/friend/spring/service/PostQueryServiceImpl.java diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 3b85256..a58532d 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -1,13 +1,18 @@ package friend.spring.converter; +import friend.spring.domain.Candidate; +import friend.spring.domain.General_poll; import friend.spring.domain.Post; import friend.spring.domain.enums.PostCategory; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; +import friend.spring.web.dto.PollOptionDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; import static friend.spring.domain.enums.PostType.*; @@ -20,6 +25,12 @@ public static PostResponseDTO.AddPostResultDTO toAddPostResultDTO(Post post) { .build(); } + public static PollOptionDTO toPollOptionDTO(Candidate candidate){ + return PollOptionDTO.builder() + .optionString(candidate.getName()) + .optionImg(candidate.getImage()).build(); + } + public static Post toPost(PostRequestDTO.AddPostDTO request) { PostType postType=null; PostVoteType postVoteType=null; @@ -87,6 +98,69 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { .state(PostState.POSTING) .build(); } + + public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post){ + Integer likeCount = post.getPostLikeList().size(); + Integer commentCount = post.getCommentList().size(); + + + if(post.getPostType()==REVIEW){ + return PostResponseDTO.PostDetailResponse.builder() + .nickname(post.getUser().getNickname()) + .createdAt(post.getCreatedAt()) + .title(post.getTitle()) + .content(post.getContent()) + .parentId(post.getParentPost().getId()) + .view(post.getView()) + .like(likeCount) + .comment(commentCount) + .build(); + } + if(post.getVoteType()==PostVoteType.GAUGE){ + return PostResponseDTO.PostDetailResponse.builder() + .nickname(post.getUser().getNickname()) + .createdAt(post.getCreatedAt()) + .title(post.getTitle()) + .content(post.getContent()) + .gauge(post.getGaugePoll().getGauge()) + .point(post.getPoint()) + .view(post.getView()) + .like(likeCount) + .comment(commentCount) + .build(); + } + List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + if(post.getVoteType()==PostVoteType.GENERAL){ + return PostResponseDTO.PostDetailResponse.builder() + .nickname(post.getUser().getNickname()) + .createdAt(post.getCreatedAt()) + .title(post.getTitle()) + .content(post.getContent()) + .pollTitle(post.getGeneralPoll().getPollTitle()) + .pollOption(pollOptionDTOList) + .point(post.getPoint()) + .deadline(post.getGeneralPoll().getDeadline()) + .view(post.getView()) + .like(likeCount) + .comment(commentCount) + .build(); + } + + return PostResponseDTO.PostDetailResponse.builder() + .nickname(post.getUser().getNickname()) + .createdAt(post.getCreatedAt()) + .title(post.getTitle()) + .content(post.getContent()) + .pollTitle(post.getCardPoll().getPollTitle()) + .pollOption(pollOptionDTOList) + .point(post.getPoint()) + .deadline(post.getCardPoll().getDeadline()) + .view(post.getView()) + .like(likeCount) + .comment(commentCount) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 5a9f347..55ae6ad 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -111,6 +111,10 @@ public void setParentPost(Post parent){ parent.getReviewPostList().add(this); } + public void setView(Integer view) { + this.view = view; + } + public void setGeneralPoll(General_poll generalPoll) { this.generalPoll = generalPoll; if (generalPoll != null && generalPoll.getPost() != this) { diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java new file mode 100644 index 0000000..632f765 --- /dev/null +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -0,0 +1,9 @@ +package friend.spring.service; + +import friend.spring.domain.Post; + +import java.util.Optional; + +public interface PostQueryService { + Optional getPostDetail(Long postId); +} diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java new file mode 100644 index 0000000..55cf3d5 --- /dev/null +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -0,0 +1,27 @@ +package friend.spring.service; + +import friend.spring.converter.PostConverter; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.repository.PostRepository; +import friend.spring.web.dto.PostResponseDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.persistence.EntityNotFoundException; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class PostQueryServiceImpl implements PostQueryService{ + private final PostRepository postRepository; + @Override + @Transactional + public Optional getPostDetail(Long postId){ + Optional postOptional=postRepository.findById(postId); + Post post = postOptional.get(); + post.setView(post.getView()+1); + return postOptional; + } +} diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 5466826..70dccf3 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -2,6 +2,8 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.PostConverter; import friend.spring.domain.Post; +import friend.spring.repository.PostRepository; +import friend.spring.service.PostQueryService; import friend.spring.service.PostService; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; @@ -9,16 +11,21 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; +import java.util.Optional; + @RestController @RequiredArgsConstructor @Validated @RequestMapping("/posts") public class PostRestController { private final PostService postService; + private final PostQueryService postQueryService; + private final PostRepository postRepository; @PostMapping("/{user-id}") @Operation(summary = "글 작성 API", description = "글을 추가 합니다.") @Parameters({ @@ -41,4 +48,14 @@ public ApiResponse join(@RequestBody @Valid Po Post post= postService.joinPost(request,UserId); return ApiResponse.onSuccess(PostConverter.toAddPostResultDTO(post)); } + + @GetMapping("/{post-id}") + @Operation(summary = "글 상세 보기 API", description = "글 상세 보기합니다.") + public ApiResponse getPostDetail(@PathVariable(name="post-id")Long PostId){ + Optional postOptional =postQueryService.getPostDetail(PostId); +// Optional postOptional =postRepository.findById(PostId); + Post post = postOptional.get(); + return ApiResponse.onSuccess(PostConverter.postDetailResponse(post)); + + } } diff --git a/src/main/java/friend/spring/web/dto/PollOptionDTO.java b/src/main/java/friend/spring/web/dto/PollOptionDTO.java index bceb000..06b0e24 100644 --- a/src/main/java/friend/spring/web/dto/PollOptionDTO.java +++ b/src/main/java/friend/spring/web/dto/PollOptionDTO.java @@ -1,8 +1,12 @@ package friend.spring.web.dto; -import lombok.Getter; +import lombok.*; @Getter +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor public class PollOptionDTO { private String optionString; private String optionImg; diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 8faf54e..a60bea6 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -1,10 +1,14 @@ package friend.spring.web.dto; +import friend.spring.domain.Candidate; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import java.sql.Timestamp; import java.time.LocalDateTime; +import java.util.List; + public class PostResponseDTO { @Builder @Data @@ -14,4 +18,25 @@ public static class AddPostResultDTO { Long postId; LocalDateTime createdAt; } + + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class PostDetailResponse { + String nickname; + LocalDateTime createdAt; + String title; + String content; + String pollTitle; // 투표글에서만 사용, 후기글에서는 null + List pollOption; // 투표글에서만 사용, 후기글에서는 null + Integer gauge; // 게이지 투표글에서만 사용, 후기글에서는 null + Integer point; // 투표글에서만 사용, 후기글에서는 null + Long parentId; // 후기글에서만 사용, 일반글에서는 null + Timestamp deadline; // 투표글에서만 사용, 후기글에서는 null + Integer view; + Integer like; + Integer comment; + + } } \ No newline at end of file From 12f1f1f7ed72ef9237f58e804b30686d59179045 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Fri, 2 Feb 2024 03:11:45 +0900 Subject: [PATCH 096/255] =?UTF-8?q?#42=20docs=20:=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80(Q&A=EC=A7=88=EB=AC=B8,=20Q&A?= =?UTF-8?q?=EB=8B=B5=EB=B3=80)=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/UserConverter.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index d945bae..cd3c914 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -18,7 +18,7 @@ public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ .userPhoto(user.getImage()) .userName(user.getNickname()) .userPoint(user.getPoint()) - .userLevelInt(user.getLevel().getLike()) + .userLevelInt(user.getLevel().getLike()+1) .userLevelName(user.getLevel().getName()) .userRecommend(user.getLike()) .build(); @@ -36,8 +36,11 @@ public static UserResponseDTO.QuestionResDTO toQuestionResDTO(User user, Level n List myPostDTOList = postList.stream() .map(PostConverter::toMyPostResDTO).collect(Collectors.toList()); + //답변 목록 + List myCommentDTOList = commentList.stream() + .map(CommentConverter::toMyCommentResDTO).collect(Collectors.toList()); //총 답변수 - int all = commentList.getSize(); + int all = myCommentDTOList.size(); //채택 답변수 List myCommentList = commentList.stream() .filter(comment -> comment.getCommentChoiceList().isEmpty()).collect(Collectors.toList()); From cebade7ad85a7134d409db139892d2b031d05d11 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 2 Feb 2024 03:28:58 +0900 Subject: [PATCH 097/255] =?UTF-8?q?#32=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/UserConverter.java | 2 +- .../java/friend/spring/domain/Comment.java | 5 ++++ .../java/friend/spring/domain/Gauge_vote.java | 1 - src/main/java/friend/spring/domain/User.java | 4 ++-- .../friend/spring/service/CommentService.java | 1 + .../spring/service/CommentServiceImpl.java | 14 +++++++++++ .../web/controller/CommentRestController.java | 24 +++++++++++++++++++ 7 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index d945bae..5ac8173 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -86,7 +86,7 @@ public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLe //남은 다음 등급 double nxtGrade = ((double)user.getLike()/(double)(nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; return UserResponseDTO.AnswerResDTO.builder() - .userPhoto(user.getName()) + .userPhoto(user.getImage()) .nickName(user.getNickname()) .recommend(user.getLike()) .grade(user.getLevel().getName()) diff --git a/src/main/java/friend/spring/domain/Comment.java b/src/main/java/friend/spring/domain/Comment.java index a7f8cea..6d9f943 100644 --- a/src/main/java/friend/spring/domain/Comment.java +++ b/src/main/java/friend/spring/domain/Comment.java @@ -57,4 +57,9 @@ public class Comment extends BaseEntity { public void update(String content) { this.content = content; } + + public void updateStateToDeleted() { + this.state = CommentState.DELETED; + } + } diff --git a/src/main/java/friend/spring/domain/Gauge_vote.java b/src/main/java/friend/spring/domain/Gauge_vote.java index 5256858..f2e3562 100644 --- a/src/main/java/friend/spring/domain/Gauge_vote.java +++ b/src/main/java/friend/spring/domain/Gauge_vote.java @@ -15,7 +15,6 @@ public class Gauge_vote extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Builder.Default @Column(nullable = false) private Integer value; diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 9cf67f7..4968667 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -36,8 +36,8 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = false, length = 50) private String email; - @Column(nullable = false, length = 15) - private String name; +// @Column(nullable = false, length = 15) +// private String name; @Pattern(regexp = "^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$", message = "전화번호 형식이 맞지 않습니다.") @Column(nullable = false, length = 15) diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index 59a5e05..edac1ce 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -30,4 +30,5 @@ public interface CommentService { Page getMyCommentList(Long userId, Integer page); + void deleteComment(Long postId, Long commentId, Long userId); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 4c4add7..b83e485 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -242,5 +242,19 @@ public Page getMyCommentList(Long userId, Integer page) { Page userPage = commentRepository.findAllByUser(user, PageRequest.of(page, 5)); return userPage; } + + @Override + @Transactional + public void deleteComment(Long postId, Long commentId, Long userId) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + Comment comment = commentRepository.findById(commentId).orElseThrow(() -> new GeneralException(ErrorStatus.COMMENT_NOT_FOUND)); + // 로그인한 사용자가 이 댓글의 작성자인지 확인 + if (!Objects.equals(user.getId(), comment.getUser().getId())) { + // 작성자가 아닌 경우 -> 에러 반환 + this.checkCommentWriterUser(false); + } + comment.updateStateToDeleted(); + } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 2573e0c..9d086ea 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -168,4 +168,28 @@ public ApiResponse editComment( commentService.editComment(postId, commentId, request, userId); return ApiResponse.onSuccess(null); } + + // 댓글 삭제 + @PatchMapping("/{post-id}/comment/{comment-id}/like/del") + @Operation(summary = "댓글 삭제 API", description = "댓글 삭제하는 API입니다. ex) /posts/1/comment/1/del") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4005",description = "올바른 사용자(댓글 작성자)가 아닙니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "comment-id", description = "path variable - 댓글 아이디"), + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + }) + public ApiResponse deleteComment( + @PathVariable("post-id") Long postId, + @PathVariable("comment-id") Long commentId, + @RequestHeader("userId") Long userId + ) { + commentService.deleteComment(postId, commentId, userId); + return ApiResponse.onSuccess(null); + } } From b4573d30eb180812f270e597497c04c9f6dc4716 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Fri, 2 Feb 2024 03:40:24 +0900 Subject: [PATCH 098/255] =?UTF-8?q?name=EC=BB=AC=EB=9F=BC=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/converter/UserConverter.java | 13 ++++++------- src/main/java/friend/spring/domain/Level.java | 2 +- src/main/java/friend/spring/domain/User.java | 7 ++----- .../java/friend/spring/service/UserServiceImpl.java | 4 ++-- .../java/friend/spring/web/dto/UserRequestDTO.java | 1 - 5 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 1e4f703..2e43a7a 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -29,7 +29,7 @@ public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ .userName(user.getNickname()) .userPoint(user.getPoint()) .userLevelInt(user.getLevel().getLike()) - .userLevelName(user.getLevel().getName()) + .userLevelName(user.getLevel().getNickname()) .userRecommend(user.getLike()) .build(); } @@ -72,7 +72,6 @@ public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest){ .agree_info(userJoinRequest.isAgree_info()) .agree_marketing(userJoinRequest.isAgree_marketing()) .birth(userJoinRequest.getBirth()) - .name(userJoinRequest.getName()) .kakao(userJoinRequest.getKakao()) .image(userJoinRequest.getImage()) .is_deleted(userJoinRequest.is_deleted()) @@ -108,9 +107,9 @@ public static UserResponseDTO.QuestionResDTO toQuestionResDTO(User user, Level n .userPhoto(user.getImage()) .nickName(user.getNickname()) .recommend(user.getLike()) - .grade(user.getLevel().getName()) + .grade(user.getLevel().getNickname()) .nextGrade(nxtGrade) - .nextGradeName(nxtLevel.getName()) + .nextGradeName(nxtLevel.getNickname()) .adoptComments(aChoice) .adoptCommentPercent(aChoicePercent) .postNum(myPostDTOList.size()) @@ -137,12 +136,12 @@ public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLe //남은 다음 등급 double nxtGrade = ((double)user.getLike()/(double)(nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; return UserResponseDTO.AnswerResDTO.builder() - .userPhoto(user.getName()) + .userPhoto(user.getNickname()) .nickName(user.getNickname()) .recommend(user.getLike()) - .grade(user.getLevel().getName()) + .grade(user.getLevel().getNickname()) .nextGrade(nxtGrade) - .nextGradeName(nxtLevel.getName()) + .nextGradeName(nxtLevel.getNickname()) .adoptComments(choice) .adoptCommentPercent(percent) .commentList(myCommentDTOList) diff --git a/src/main/java/friend/spring/domain/Level.java b/src/main/java/friend/spring/domain/Level.java index 064f27d..bce77bc 100644 --- a/src/main/java/friend/spring/domain/Level.java +++ b/src/main/java/friend/spring/domain/Level.java @@ -18,7 +18,7 @@ public class Level extends BaseEntity { private Long id; @Column(nullable = false, length = 10) - private String name; + private String nickname; @Column(nullable = false) private Integer like; diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index e4184bb..4b85e00 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -36,9 +36,6 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = false, length = 50) private String email; - @Column(nullable = false, length = 15) //name 넣고 돌리면 name칸 비어잇어서 안되고, 없애면 오류 확인 - private String name; - @Pattern(regexp = "^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$", message = "전화번호 형식이 맞지 않습니다.") @Column(nullable = false, length = 15) private String phone; @@ -63,7 +60,7 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true) private String image; - @Column(nullable = true)//잠시 true로 수정 + @Column(nullable = false) private Boolean is_deleted; @Column(nullable = true) @@ -72,7 +69,7 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true) private String kakao; - @Column(nullable = true)//잠시 true + @Column(nullable = false) private Integer like; diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 0c335b0..0cf8fb8 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -44,12 +44,12 @@ public void checkUser(Boolean flag) { } } - public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest){ + public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest) { User newUser = UserConverter.toUser(userJoinRequest); return userRepository.saveAndFlush(newUser); - + } @Override public Level nextLevel(Long id) { Optional user = userRepository.findById(id); diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 25b3636..5bbd203 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -28,7 +28,6 @@ public static class UserJoinRequest { boolean agree_info; boolean agree_marketing; LocalDate birth; - String name; boolean is_deleted; String image; Integer point; From af0c116325bdb18e2d26def259c343e444d41036 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Fri, 2 Feb 2024 03:51:24 +0900 Subject: [PATCH 099/255] =?UTF-8?q?Revert=20"name=EC=BB=AC=EB=9F=BC?= =?UTF-8?q?=EC=88=98=EC=A0=95"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b4573d30eb180812f270e597497c04c9f6dc4716. --- .../java/friend/spring/converter/UserConverter.java | 13 +++++++------ src/main/java/friend/spring/domain/Level.java | 2 +- src/main/java/friend/spring/domain/User.java | 7 +++++-- .../java/friend/spring/service/UserServiceImpl.java | 4 ++-- .../java/friend/spring/web/dto/UserRequestDTO.java | 1 + 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 2e43a7a..1e4f703 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -29,7 +29,7 @@ public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ .userName(user.getNickname()) .userPoint(user.getPoint()) .userLevelInt(user.getLevel().getLike()) - .userLevelName(user.getLevel().getNickname()) + .userLevelName(user.getLevel().getName()) .userRecommend(user.getLike()) .build(); } @@ -72,6 +72,7 @@ public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest){ .agree_info(userJoinRequest.isAgree_info()) .agree_marketing(userJoinRequest.isAgree_marketing()) .birth(userJoinRequest.getBirth()) + .name(userJoinRequest.getName()) .kakao(userJoinRequest.getKakao()) .image(userJoinRequest.getImage()) .is_deleted(userJoinRequest.is_deleted()) @@ -107,9 +108,9 @@ public static UserResponseDTO.QuestionResDTO toQuestionResDTO(User user, Level n .userPhoto(user.getImage()) .nickName(user.getNickname()) .recommend(user.getLike()) - .grade(user.getLevel().getNickname()) + .grade(user.getLevel().getName()) .nextGrade(nxtGrade) - .nextGradeName(nxtLevel.getNickname()) + .nextGradeName(nxtLevel.getName()) .adoptComments(aChoice) .adoptCommentPercent(aChoicePercent) .postNum(myPostDTOList.size()) @@ -136,12 +137,12 @@ public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLe //남은 다음 등급 double nxtGrade = ((double)user.getLike()/(double)(nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; return UserResponseDTO.AnswerResDTO.builder() - .userPhoto(user.getNickname()) + .userPhoto(user.getName()) .nickName(user.getNickname()) .recommend(user.getLike()) - .grade(user.getLevel().getNickname()) + .grade(user.getLevel().getName()) .nextGrade(nxtGrade) - .nextGradeName(nxtLevel.getNickname()) + .nextGradeName(nxtLevel.getName()) .adoptComments(choice) .adoptCommentPercent(percent) .commentList(myCommentDTOList) diff --git a/src/main/java/friend/spring/domain/Level.java b/src/main/java/friend/spring/domain/Level.java index bce77bc..064f27d 100644 --- a/src/main/java/friend/spring/domain/Level.java +++ b/src/main/java/friend/spring/domain/Level.java @@ -18,7 +18,7 @@ public class Level extends BaseEntity { private Long id; @Column(nullable = false, length = 10) - private String nickname; + private String name; @Column(nullable = false) private Integer like; diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 4b85e00..e4184bb 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -36,6 +36,9 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = false, length = 50) private String email; + @Column(nullable = false, length = 15) //name 넣고 돌리면 name칸 비어잇어서 안되고, 없애면 오류 확인 + private String name; + @Pattern(regexp = "^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$", message = "전화번호 형식이 맞지 않습니다.") @Column(nullable = false, length = 15) private String phone; @@ -60,7 +63,7 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true) private String image; - @Column(nullable = false) + @Column(nullable = true)//잠시 true로 수정 private Boolean is_deleted; @Column(nullable = true) @@ -69,7 +72,7 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true) private String kakao; - @Column(nullable = false) + @Column(nullable = true)//잠시 true private Integer like; diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 0cf8fb8..0c335b0 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -44,12 +44,12 @@ public void checkUser(Boolean flag) { } } - public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest) { + public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest){ User newUser = UserConverter.toUser(userJoinRequest); return userRepository.saveAndFlush(newUser); - } + @Override public Level nextLevel(Long id) { Optional user = userRepository.findById(id); diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 5bbd203..25b3636 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -28,6 +28,7 @@ public static class UserJoinRequest { boolean agree_info; boolean agree_marketing; LocalDate birth; + String name; boolean is_deleted; String image; Integer point; From d6ed2265cd9cd2325a6e568c3567da64dcbdf9c1 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Fri, 2 Feb 2024 04:03:30 +0900 Subject: [PATCH 100/255] =?UTF-8?q?name=EC=BB=AC=EB=9F=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=953?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/UserConverter.java | 3 +-- src/main/java/friend/spring/domain/User.java | 3 --- src/main/java/friend/spring/service/UserServiceImpl.java | 4 ++-- src/main/java/friend/spring/web/dto/UserRequestDTO.java | 1 - 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 1e4f703..e6ea0ac 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -72,7 +72,6 @@ public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest){ .agree_info(userJoinRequest.isAgree_info()) .agree_marketing(userJoinRequest.isAgree_marketing()) .birth(userJoinRequest.getBirth()) - .name(userJoinRequest.getName()) .kakao(userJoinRequest.getKakao()) .image(userJoinRequest.getImage()) .is_deleted(userJoinRequest.is_deleted()) @@ -137,7 +136,7 @@ public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLe //남은 다음 등급 double nxtGrade = ((double)user.getLike()/(double)(nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; return UserResponseDTO.AnswerResDTO.builder() - .userPhoto(user.getName()) + .userPhoto(user.getImage()) .nickName(user.getNickname()) .recommend(user.getLike()) .grade(user.getLevel().getName()) diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index e4184bb..9621b1e 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -36,9 +36,6 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = false, length = 50) private String email; - @Column(nullable = false, length = 15) //name 넣고 돌리면 name칸 비어잇어서 안되고, 없애면 오류 확인 - private String name; - @Pattern(regexp = "^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$", message = "전화번호 형식이 맞지 않습니다.") @Column(nullable = false, length = 15) private String phone; diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 0c335b0..0cf8fb8 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -44,12 +44,12 @@ public void checkUser(Boolean flag) { } } - public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest){ + public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest) { User newUser = UserConverter.toUser(userJoinRequest); return userRepository.saveAndFlush(newUser); - + } @Override public Level nextLevel(Long id) { Optional user = userRepository.findById(id); diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 25b3636..5bbd203 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -28,7 +28,6 @@ public static class UserJoinRequest { boolean agree_info; boolean agree_marketing; LocalDate birth; - String name; boolean is_deleted; String image; Integer point; From 9d6874074ba7b3fea3442e7a4d6868b27b4eee59 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Fri, 2 Feb 2024 04:11:31 +0900 Subject: [PATCH 101/255] =?UTF-8?q?#42=20docs=20:=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80(Q&A=EC=A7=88=EB=AC=B8,=20Q&A?= =?UTF-8?q?=EB=8B=B5=EB=B3=80)=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/UserConverter.java | 7 ++---- .../spring/web/dto/AlarmResponseDTO.java | 23 +++++++++++++++++++ .../spring/web/dto/UserResponseDTO.java | 2 -- 3 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 src/main/java/friend/spring/web/dto/AlarmResponseDTO.java diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index d945bae..c81d214 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -1,9 +1,7 @@ package friend.spring.converter; -import friend.spring.domain.Comment; -import friend.spring.domain.Level; -import friend.spring.domain.Post; -import friend.spring.domain.User; +import friend.spring.domain.*; +import friend.spring.web.dto.AlarmResponseDTO; import friend.spring.web.dto.CommentResponseDTO; import friend.spring.web.dto.PostResponseDTO; import friend.spring.web.dto.UserResponseDTO; @@ -98,5 +96,4 @@ public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLe .build(); } - } diff --git a/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java b/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java new file mode 100644 index 0000000..63475a5 --- /dev/null +++ b/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java @@ -0,0 +1,23 @@ +package friend.spring.web.dto; + +import friend.spring.domain.enums.AlarmType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +public class AlarmResponseDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class AlarmResDTO{ + String nickName; + AlarmType type; + String content; + LocalDateTime dateTime; + } +} diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index a8cd200..a8e02e0 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -96,6 +96,4 @@ public static class AnswerResDTO { Double adoptCommentPercent; List commentList; } - - } \ No newline at end of file From e17692e32ba2170c712d2e116b45c9b81babd4ca Mon Sep 17 00:00:00 2001 From: ls-rain Date: Fri, 2 Feb 2024 06:37:36 +0900 Subject: [PATCH 102/255] =?UTF-8?q?#51=20Feat=20:=20=EC=95=8C=EB=A6=BC=20A?= =?UTF-8?q?PI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 3 ++ .../apiPayload/handler/AlarmHandler.java | 8 ++++ .../spring/converter/AlarmConverter.java | 29 ++++++++++++ .../spring/converter/UserConverter.java | 10 +---- .../spring/repository/AlarmRepository.java | 11 +++++ .../friend/spring/service/AlarmService.java | 11 +++++ .../spring/service/AlarmServiceImpl.java | 44 +++++++++++++++++++ .../web/controller/AlarmRestController.java | 41 +++++++++++++++++ .../web/controller/UserRestController.java | 7 +++ .../spring/web/dto/AlarmResponseDTO.java | 10 ++++- 10 files changed, 165 insertions(+), 9 deletions(-) create mode 100644 src/main/java/friend/spring/apiPayload/handler/AlarmHandler.java create mode 100644 src/main/java/friend/spring/converter/AlarmConverter.java create mode 100644 src/main/java/friend/spring/repository/AlarmRepository.java create mode 100644 src/main/java/friend/spring/service/AlarmService.java create mode 100644 src/main/java/friend/spring/service/AlarmServiceImpl.java create mode 100644 src/main/java/friend/spring/web/controller/AlarmRestController.java diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 68ca9c7..7246178 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -39,6 +39,9 @@ public enum ErrorStatus implements BaseErrorCode { COMMENT_SELECT_MYSELF(HttpStatus.BAD_REQUEST, "COMMENT4004", "자기 자신은 채택할 수 없습니다."), COMMENT_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "COMMENT4005", "올바른 사용자(댓글 작성자)가 아닙니다."), + // 알림 관련 응답 + ALARM_NOT_FOUND(HttpStatus.NOT_FOUND, "ALARM4001", "알림이 없습니다") + ; private final HttpStatus httpStatus; diff --git a/src/main/java/friend/spring/apiPayload/handler/AlarmHandler.java b/src/main/java/friend/spring/apiPayload/handler/AlarmHandler.java new file mode 100644 index 0000000..ec9f5dc --- /dev/null +++ b/src/main/java/friend/spring/apiPayload/handler/AlarmHandler.java @@ -0,0 +1,8 @@ +package friend.spring.apiPayload.handler; + +import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.code.BaseErrorCode; + +public class AlarmHandler extends GeneralException { + public AlarmHandler(BaseErrorCode errorCode){super(errorCode);} +} diff --git a/src/main/java/friend/spring/converter/AlarmConverter.java b/src/main/java/friend/spring/converter/AlarmConverter.java new file mode 100644 index 0000000..b6044d8 --- /dev/null +++ b/src/main/java/friend/spring/converter/AlarmConverter.java @@ -0,0 +1,29 @@ +package friend.spring.converter; + +import friend.spring.domain.Alarm; +import friend.spring.web.dto.AlarmResponseDTO; +import org.springframework.data.domain.Page; + +import java.util.List; +import java.util.stream.Collectors; + +public class AlarmConverter { + + //알림 + public static AlarmResponseDTO.AlarmResDTO toAlarmResDTO(Alarm alarm){ + return AlarmResponseDTO.AlarmResDTO.builder() + .nickName(alarm.getUser().getNickname()) + .type(alarm.getType()) + .content(alarm.getContent()) + .createdAt(alarm.getCreatedAt()) + .build(); + } + + public static AlarmResponseDTO.AlarmListResDTO toAlarmListResDTO(Page alarmList){ + List alarmResDTOList = alarmList.stream() + .map(AlarmConverter::toAlarmResDTO).collect(Collectors.toList()); + return AlarmResponseDTO.AlarmListResDTO.builder() + .alarmList(alarmResDTOList) + .build(); + } +} diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index e6ea0ac..d860a83 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -1,19 +1,13 @@ package friend.spring.converter; -import friend.spring.domain.Comment; -import friend.spring.domain.Level; -import friend.spring.domain.Post; -import friend.spring.domain.User; +import friend.spring.domain.*; import friend.spring.domain.enums.Gender; -import friend.spring.web.dto.UserRequestDTO; -import friend.spring.web.dto.UserResponseDTO; +import friend.spring.web.dto.*; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import java.time.LocalDate; import java.time.LocalDateTime; -import friend.spring.web.dto.CommentResponseDTO; -import friend.spring.web.dto.PostResponseDTO; import friend.spring.web.dto.UserResponseDTO; import org.springframework.data.domain.Page; diff --git a/src/main/java/friend/spring/repository/AlarmRepository.java b/src/main/java/friend/spring/repository/AlarmRepository.java new file mode 100644 index 0000000..3355c52 --- /dev/null +++ b/src/main/java/friend/spring/repository/AlarmRepository.java @@ -0,0 +1,11 @@ +package friend.spring.repository; + +import friend.spring.domain.Alarm; +import friend.spring.domain.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AlarmRepository extends JpaRepository { + Page findAllByUser(User user, PageRequest pageRequest); +} diff --git a/src/main/java/friend/spring/service/AlarmService.java b/src/main/java/friend/spring/service/AlarmService.java new file mode 100644 index 0000000..afc2d86 --- /dev/null +++ b/src/main/java/friend/spring/service/AlarmService.java @@ -0,0 +1,11 @@ +package friend.spring.service; + +import friend.spring.domain.Alarm; +import org.springframework.data.domain.Page; + +public interface AlarmService { + + void checkAlarm(boolean flag); + + Page getAlarmList(Long userId, Integer page); +} diff --git a/src/main/java/friend/spring/service/AlarmServiceImpl.java b/src/main/java/friend/spring/service/AlarmServiceImpl.java new file mode 100644 index 0000000..801a827 --- /dev/null +++ b/src/main/java/friend/spring/service/AlarmServiceImpl.java @@ -0,0 +1,44 @@ +package friend.spring.service; + +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.apiPayload.handler.AlarmHandler; +import friend.spring.domain.Alarm; +import friend.spring.domain.User; +import friend.spring.repository.AlarmRepository; +import friend.spring.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Service +@RequiredArgsConstructor +@Transactional +public class AlarmServiceImpl implements AlarmService{ + + private final UserRepository userRepository; + private final AlarmRepository alarmRepository; + private final UserService userService; + @Override + public void checkAlarm(boolean flag) { + if (!flag){ + throw new AlarmHandler(ErrorStatus.ALARM_NOT_FOUND); + } + } + + @Override + public Page getAlarmList(Long userId, Integer page) { + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + User user = optionalUser.get(); + + Page alarmPage = alarmRepository.findAllByUser(user, PageRequest.of(page, 10)); + return alarmPage; + + } +} diff --git a/src/main/java/friend/spring/web/controller/AlarmRestController.java b/src/main/java/friend/spring/web/controller/AlarmRestController.java new file mode 100644 index 0000000..dae56b4 --- /dev/null +++ b/src/main/java/friend/spring/web/controller/AlarmRestController.java @@ -0,0 +1,41 @@ +package friend.spring.web.controller; + +import friend.spring.apiPayload.ApiResponse; +import friend.spring.converter.AlarmConverter; +import friend.spring.domain.Alarm; +import friend.spring.service.AlarmService; +import friend.spring.web.dto.AlarmResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/user") +public class AlarmRestController { + + private final AlarmService alarmService; + //알림 조회 + @GetMapping("/alarm") + @Operation(summary = "사용자 알림 조회 API",description = "사용자의 알림 목록을 조회하는 API이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "ALARM4001",description = "NOT_FOUND, 알림을 찾을 수 없습니다."), + + }) + @Parameters({ + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)") + }) + private ApiResponse getAlarm( + @RequestHeader(name = "id") Long userId, + @RequestParam(name = "page") Integer page){ + Page alarmList = alarmService.getAlarmList(userId, page); + return ApiResponse.onSuccess(AlarmConverter.toAlarmListResDTO(alarmList)); + } +} diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index b2cfd59..c4dca64 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -12,6 +12,7 @@ import friend.spring.service.PostService; import friend.spring.service.UserService; import friend.spring.service.UserServiceImpl; +import friend.spring.web.dto.AlarmResponseDTO; import friend.spring.web.dto.UserRequestDTO; import friend.spring.web.dto.UserResponseDTO; import io.swagger.annotations.Api; @@ -32,6 +33,8 @@ public class UserRestController { private final EmailService mailService; private final PostService postService; private final CommentService commentService; + + //마이 페이지 조회 @GetMapping("/my-page") public ApiResponse getMyPage( @RequestHeader(name = "id") Long userId) { @@ -53,6 +56,8 @@ public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailS mailService.CheckAuthNum(emailSendCheckReq.getEmail(), emailSendCheckReq.getAuthNum()); return ApiResponse.onSuccess(null); } + + //나의 Q&A 질문 조회 @GetMapping("/my-page/profile/question") public ApiResponse getQuestion( @RequestHeader(name = "id") Long userId, @@ -64,6 +69,7 @@ public ApiResponse getQuestion( return ApiResponse.onSuccess(UserConverter.toQuestionResDTO(myPage, nxtLevel, myPostList, myCommentList)); } + //나의 Q&A 답변 조회 @GetMapping("/my-page/profile/answer") public ApiResponse getAnswer( @RequestHeader(name = "id") Long userId, @@ -80,5 +86,6 @@ public ApiResponse join(@RequestBody @Valid UserR return ApiResponse.onSuccess(UserConverter.joinResultDTO(user)); } + } diff --git a/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java b/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java index 63475a5..8d43fb5 100644 --- a/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java @@ -7,9 +7,17 @@ import lombok.NoArgsConstructor; import java.time.LocalDateTime; +import java.util.List; public class AlarmResponseDTO { + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class AlarmListResDTO{ + List alarmList; + } @Builder @Getter @NoArgsConstructor @@ -18,6 +26,6 @@ public static class AlarmResDTO{ String nickName; AlarmType type; String content; - LocalDateTime dateTime; + LocalDateTime createdAt; } } From 51c5b1be37ef3d615cb769eb3dfeb5a2f0f1f316 Mon Sep 17 00:00:00 2001 From: hjh <98207658+jjjuhoon@users.noreply.github.com> Date: Fri, 2 Feb 2024 21:53:28 +0900 Subject: [PATCH 103/255] =?UTF-8?q?#48=20Feat:=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C(=EB=AF=B8=EC=99=84=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/PostConverter.java | 7 +++++-- src/main/java/friend/spring/service/PostQueryService.java | 1 + .../java/friend/spring/service/PostQueryServiceImpl.java | 8 ++++++++ .../friend/spring/web/controller/PostRestController.java | 8 +++++--- src/main/java/friend/spring/web/dto/PostResponseDTO.java | 3 +++ 5 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index a58532d..8046f08 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -2,6 +2,7 @@ import friend.spring.domain.Candidate; import friend.spring.domain.General_poll; import friend.spring.domain.Post; +import friend.spring.domain.User; import friend.spring.domain.enums.PostCategory; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; @@ -99,11 +100,13 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { .build(); } - public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post){ + public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, Boolean engage){ Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); + + if(post.getPostType()==REVIEW){ return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) @@ -129,7 +132,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post){ .comment(commentCount) .build(); } - List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() + List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); if(post.getVoteType()==PostVoteType.GENERAL){ return PostResponseDTO.PostDetailResponse.builder() diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index 632f765..94d8904 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -6,4 +6,5 @@ public interface PostQueryService { Optional getPostDetail(Long postId); + Boolean checkEngage(Long userId, Long postId); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 55cf3d5..398c05a 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -4,6 +4,7 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.repository.PostRepository; +import friend.spring.repository.UserRepository; import friend.spring.web.dto.PostResponseDTO; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -16,6 +17,7 @@ @RequiredArgsConstructor public class PostQueryServiceImpl implements PostQueryService{ private final PostRepository postRepository; + private final UserRepository userRepository; @Override @Transactional public Optional getPostDetail(Long postId){ @@ -24,4 +26,10 @@ public Optional getPostDetail(Long postId){ post.setView(post.getView()+1); return postOptional; } + + @Override + public Boolean checkEngage(Long userId,Long postId){ + Boolean engage = postRepository.f + return postOptional; + } } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 70dccf3..a8bbc9d 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -49,13 +49,15 @@ public ApiResponse join(@RequestBody @Valid Po return ApiResponse.onSuccess(PostConverter.toAddPostResultDTO(post)); } - @GetMapping("/{post-id}") + @GetMapping("/{post-id}/{user-id}") @Operation(summary = "글 상세 보기 API", description = "글 상세 보기합니다.") - public ApiResponse getPostDetail(@PathVariable(name="post-id")Long PostId){ + public ApiResponse getPostDetail(@PathVariable(name="post-id")Long PostId, + @PathVariable(name="user-id")Long userId){ Optional postOptional =postQueryService.getPostDetail(PostId); // Optional postOptional =postRepository.findById(PostId); + Boolean engage=postQueryService. Post post = postOptional.get(); - return ApiResponse.onSuccess(PostConverter.postDetailResponse(post)); + return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage)); } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index a60bea6..4a1db73 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -34,6 +34,9 @@ public static class PostDetailResponse { Integer point; // 투표글에서만 사용, 후기글에서는 null Long parentId; // 후기글에서만 사용, 일반글에서는 null Timestamp deadline; // 투표글에서만 사용, 후기글에서는 null + List userVote; // 투표글에서 사용자가 투표완료시 투표한 후보 + Integer percent; // 투표글에서 사용자가 투표 완료시 투표한 후보 선택 퍼센트 + String voteResult; // 투표글에서 사용자가 투표 완료시 투표인원/총인원 Integer view; Integer like; Integer comment; From bf025a3dca5773b669c8d4a27a5787be053f6848 Mon Sep 17 00:00:00 2001 From: hjh Date: Sat, 3 Feb 2024 01:21:24 +0900 Subject: [PATCH 104/255] =?UTF-8?q?#48=20Feat:=EB=A6=AC=EB=B7=B0=EA=B8=80?= =?UTF-8?q?=20=EC=A0=9C=EC=99=B8=20=EC=83=81=EC=84=B8=20=EB=B3=B4=EA=B8=B0?= =?UTF-8?q?=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 123 ++++++++++++++++-- .../java/friend/spring/domain/Gauge_poll.java | 4 + src/main/java/friend/spring/domain/Post.java | 1 + .../repository/Card_VoteRepository.java | 3 + .../repository/Gauge_PollRepository.java | 4 + .../repository/Gauge_VoteRepository.java | 3 + .../repository/General_VoteRepository.java | 3 + .../spring/service/PostQueryServiceImpl.java | 47 ++++++- .../spring/service/VoteServiceImpl.java | 11 ++ .../web/controller/PostRestController.java | 4 +- .../spring/web/dto/PostResponseDTO.java | 6 +- 11 files changed, 187 insertions(+), 22 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 8046f08..4ff400f 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -1,8 +1,5 @@ package friend.spring.converter; -import friend.spring.domain.Candidate; -import friend.spring.domain.General_poll; -import friend.spring.domain.Post; -import friend.spring.domain.User; +import friend.spring.domain.*; import friend.spring.domain.enums.PostCategory; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; @@ -13,6 +10,9 @@ import java.time.LocalDateTime; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; import static friend.spring.domain.enums.PostType.*; @@ -32,6 +32,8 @@ public static PollOptionDTO toPollOptionDTO(Candidate candidate){ .optionImg(candidate.getImage()).build(); } + + public static Post toPost(PostRequestDTO.AddPostDTO request) { PostType postType=null; PostVoteType postVoteType=null; @@ -100,11 +102,13 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { .build(); } - public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, Boolean engage){ + public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, Boolean engage,Long userId){ Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); - - + List userChoiceList=null; + List percent=null; + List voteResult=null; + Integer value=null; if(post.getPostType()==REVIEW){ @@ -120,21 +124,69 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .build(); } if(post.getVoteType()==PostVoteType.GAUGE){ + if(engage){ + value=post.getGaugePoll().getGauge(); + } return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .gauge(post.getGaugePoll().getGauge()) + .gauge(value) .point(post.getPoint()) + .deadline(post.getGaugePoll().getDeadline()) .view(post.getView()) .like(likeCount) .comment(commentCount) .build(); } - List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); if(post.getVoteType()==PostVoteType.GENERAL){ + List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + if(engage) { + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(generalVote -> generalVote.getUser().getId().equals(userId)) + .flatMap(generalVote -> generalVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionDTO) + .collect(Collectors.toList()); + + // 총 투표수 계산 + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); + + // 총 투표수 계산 + long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + // 사용자가 선택한 후보의 선택률 계산 + percent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) + voteResult = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + } return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) .createdAt(post.getCreatedAt()) @@ -144,12 +196,60 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .pollOption(pollOptionDTOList) .point(post.getPoint()) .deadline(post.getGeneralPoll().getDeadline()) + .userVote(userChoiceList) + .percent(percent) + .voteResult(voteResult) .view(post.getView()) .like(likeCount) .comment(commentCount) .build(); } + List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + if(engage) { + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionDTO) + .collect(Collectors.toList()); + // 총 투표수 계산 + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); + + // 총 투표수 계산 + long totalVotes = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + // 사용자가 선택한 후보의 선택률 계산 + percent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) + voteResult = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + } return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) .createdAt(post.getCreatedAt()) @@ -159,6 +259,9 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .pollOption(pollOptionDTOList) .point(post.getPoint()) .deadline(post.getCardPoll().getDeadline()) + .userVote(userChoiceList) + .percent(percent) + .voteResult(voteResult) .view(post.getView()) .like(likeCount) .comment(commentCount) diff --git a/src/main/java/friend/spring/domain/Gauge_poll.java b/src/main/java/friend/spring/domain/Gauge_poll.java index 4930367..31b7b4a 100644 --- a/src/main/java/friend/spring/domain/Gauge_poll.java +++ b/src/main/java/friend/spring/domain/Gauge_poll.java @@ -40,4 +40,8 @@ public class Gauge_poll extends BaseEntity { public void setPost(Post post) { this.post = post; } + + public void setGauge(Integer gauge) { + this.gauge = gauge; + } } diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 55ae6ad..0444cb8 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -115,6 +115,7 @@ public void setView(Integer view) { this.view = view; } + public void setGeneralPoll(General_poll generalPoll) { this.generalPoll = generalPoll; if (generalPoll != null && generalPoll.getPost() != this) { diff --git a/src/main/java/friend/spring/repository/Card_VoteRepository.java b/src/main/java/friend/spring/repository/Card_VoteRepository.java index e45b383..dda4f9f 100644 --- a/src/main/java/friend/spring/repository/Card_VoteRepository.java +++ b/src/main/java/friend/spring/repository/Card_VoteRepository.java @@ -4,5 +4,8 @@ import friend.spring.domain.Gauge_poll; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface Card_VoteRepository extends JpaRepository { + List findByUserId(Long user_id); } diff --git a/src/main/java/friend/spring/repository/Gauge_PollRepository.java b/src/main/java/friend/spring/repository/Gauge_PollRepository.java index bda947d..c764b26 100644 --- a/src/main/java/friend/spring/repository/Gauge_PollRepository.java +++ b/src/main/java/friend/spring/repository/Gauge_PollRepository.java @@ -1,7 +1,11 @@ package friend.spring.repository; import friend.spring.domain.Gauge_poll; +import friend.spring.domain.Gauge_vote; +import friend.spring.domain.General_vote; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface Gauge_PollRepository extends JpaRepository { } diff --git a/src/main/java/friend/spring/repository/Gauge_VoteRepository.java b/src/main/java/friend/spring/repository/Gauge_VoteRepository.java index 0525e8e..b5d4b8e 100644 --- a/src/main/java/friend/spring/repository/Gauge_VoteRepository.java +++ b/src/main/java/friend/spring/repository/Gauge_VoteRepository.java @@ -4,5 +4,8 @@ import friend.spring.domain.Gauge_vote; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface Gauge_VoteRepository extends JpaRepository { + List findByUserId(Long user_id); } diff --git a/src/main/java/friend/spring/repository/General_VoteRepository.java b/src/main/java/friend/spring/repository/General_VoteRepository.java index 532d41a..aa7ea7b 100644 --- a/src/main/java/friend/spring/repository/General_VoteRepository.java +++ b/src/main/java/friend/spring/repository/General_VoteRepository.java @@ -3,5 +3,8 @@ import friend.spring.domain.General_vote; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface General_VoteRepository extends JpaRepository { + List findByUserId(Long user_id); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 398c05a..96c4866 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -1,16 +1,17 @@ package friend.spring.service; import friend.spring.converter.PostConverter; -import friend.spring.domain.Post; -import friend.spring.domain.User; -import friend.spring.repository.PostRepository; -import friend.spring.repository.UserRepository; +import friend.spring.domain.*; +import friend.spring.domain.enums.PostType; +import friend.spring.domain.enums.PostVoteType; +import friend.spring.repository.*; import friend.spring.web.dto.PostResponseDTO; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityNotFoundException; +import java.util.List; import java.util.Optional; @Service @@ -18,6 +19,9 @@ public class PostQueryServiceImpl implements PostQueryService{ private final PostRepository postRepository; private final UserRepository userRepository; + private final General_VoteRepository generalVoteRepository; + private final Gauge_VoteRepository gaugeVoteRepository; + private final Card_VoteRepository cardVoteRepository; @Override @Transactional public Optional getPostDetail(Long postId){ @@ -28,8 +32,37 @@ public Optional getPostDetail(Long postId){ } @Override - public Boolean checkEngage(Long userId,Long postId){ - Boolean engage = postRepository.f - return postOptional; + public Boolean checkEngage(Long postId,Long userId){ + Optional postOptional=postRepository.findById(postId); + Post post = postOptional.get(); + Boolean engage; + if(post.getUser().getId().equals(userId)){ + return true; + } + if(post.getPostType()== PostType.VOTE){ + if(post.getVoteType()== PostVoteType.GENERAL){ + List vote=generalVoteRepository.findByUserId(userId); + if (!vote.isEmpty()) { // 목록이 비어 있지 않으면 true를 반환 + return true; + } + } + } + if(post.getPostType()== PostType.VOTE){ + if(post.getVoteType()== PostVoteType.CARD){ + List vote=cardVoteRepository.findByUserId(userId); + if (!vote.isEmpty()) { // 목록이 비어 있지 않으면 true를 반환 + return true; + } + } + } + if(post.getPostType()== PostType.VOTE){ + if(post.getVoteType()== PostVoteType.GAUGE){ + List vote=gaugeVoteRepository.findByUserId(userId); + if (!vote.isEmpty()) { // 목록이 비어 있지 않으면 true를 반환 + return true; + } + } + } + return false; } } diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index ba0bed1..ff07493 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -9,6 +9,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @Service @@ -20,6 +21,7 @@ public class VoteServiceImpl implements VoteService{ private final Card_VoteRepository cardVoteRepository; private final PostRepository postRepository; private final PointRepository pointRepository; + private final Gauge_PollRepository gaugePollRepository; @Override @Transactional public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId) { @@ -81,6 +83,15 @@ public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long newPoint.setUser(user); pointRepository.save(newPoint); + Integer value=request.getValue(); + gaugePollRepository.findById(request.getPostId()); + Optional optionalPost=postRepository.findById(request.getPostId()); + Post gaugePost=optionalPost.get(); + Integer currentGauge=gaugePost.getGaugePoll().getGauge(); + Integer engagedUser=gaugePost.getGaugePoll().getGaugeVoteList().size(); + gaugePost.getGaugePoll().setGauge((currentGauge+request.getValue())/engagedUser); + + return gaugeVoteRepository.save(newGaugeVote); } @Override diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index a8bbc9d..7800a48 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -55,9 +55,9 @@ public ApiResponse getPostDetail(@PathVariab @PathVariable(name="user-id")Long userId){ Optional postOptional =postQueryService.getPostDetail(PostId); // Optional postOptional =postRepository.findById(PostId); - Boolean engage=postQueryService. + Boolean engage=postQueryService.checkEngage(PostId,userId); Post post = postOptional.get(); - return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage)); + return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage,userId)); } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 4a1db73..b714676 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -34,9 +34,9 @@ public static class PostDetailResponse { Integer point; // 투표글에서만 사용, 후기글에서는 null Long parentId; // 후기글에서만 사용, 일반글에서는 null Timestamp deadline; // 투표글에서만 사용, 후기글에서는 null - List userVote; // 투표글에서 사용자가 투표완료시 투표한 후보 - Integer percent; // 투표글에서 사용자가 투표 완료시 투표한 후보 선택 퍼센트 - String voteResult; // 투표글에서 사용자가 투표 완료시 투표인원/총인원 + List userVote; // 투표글에서 사용자가 투표완료시 투표한 후보 + List percent; // 투표글에서 사용자가 투표 완료시 투표한 후보 선택 퍼센트 + List voteResult; // 투표글에서 사용자가 투표 완료시 투표인원/총인원 Integer view; Integer like; Integer comment; From bee2b73c68de6208011fb599353d04eb5a77a6c1 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 3 Feb 2024 04:53:00 +0900 Subject: [PATCH 105/255] =?UTF-8?q?#33=20Feat:=20=EA=B8=80=20=EC=B6=94?= =?UTF-8?q?=EC=B2=9C(=EC=A2=8B=EC=95=84=EC=9A=94)=20=EC=83=9D=EC=84=B1/?= =?UTF-8?q?=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 1 + .../spring/converter/PostConverter.java | 14 +++++ .../spring/repository/PostLikeRepository.java | 15 +++++ .../friend/spring/service/PostService.java | 7 +++ .../spring/service/PostServiceImpl.java | 55 ++++++++++++++++++- .../web/controller/PostRestController.java | 47 ++++++++++++++++ .../spring/web/dto/PostResponseDTO.java | 8 +++ 7 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/main/java/friend/spring/repository/PostLikeRepository.java diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 68ca9c7..93bdbbb 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -31,6 +31,7 @@ public enum ErrorStatus implements BaseErrorCode { // 글 관련 응답 POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "글을 찾을 수 없습니다."), POST_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "POST4002", "올바른 사용자(글 작성자)가 아닙니다."), + POST_LIKE_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4003", "글에 대한 좋아요 데이터를 찾을 수 없습니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 8dc1467..46b5b22 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -1,9 +1,11 @@ package friend.spring.converter; import friend.spring.domain.Post; +import friend.spring.domain.User; import friend.spring.domain.enums.PostCategory; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; +import friend.spring.domain.mapping.Post_like; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; @@ -98,6 +100,18 @@ public static PostResponseDTO.MyPostDTO toMyPostResDTO(Post post){ .build(); } + public static Post_like toPostLike(Post post, User user) { + return Post_like.builder() + .post(post) + .user(user) + .build(); + } + + public static PostResponseDTO.PostLikeRes toPostLikeRes(Post_like post_like) { + return PostResponseDTO.PostLikeRes.builder() + .post_like_id(post_like.getId()) + .build(); + } } diff --git a/src/main/java/friend/spring/repository/PostLikeRepository.java b/src/main/java/friend/spring/repository/PostLikeRepository.java new file mode 100644 index 0000000..b0e6d4b --- /dev/null +++ b/src/main/java/friend/spring/repository/PostLikeRepository.java @@ -0,0 +1,15 @@ +package friend.spring.repository; + +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.domain.mapping.Post_like; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface PostLikeRepository extends JpaRepository { + + Optional findByPostIdAndUserId(Long postId, Long userId); +} diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index 7ebc06a..25643da 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -3,6 +3,7 @@ import friend.spring.domain.Post; import friend.spring.domain.User; +import friend.spring.domain.mapping.Post_like; import friend.spring.web.dto.PostRequestDTO; import org.springframework.data.domain.Page; @@ -11,10 +12,16 @@ public interface PostService { void checkPostWriterUser(Boolean flag); + void checkPostLike(Boolean flag); + Post joinPost(PostRequestDTO.AddPostDTO request, Long userId); Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user); Page getMyPostList(Long userId, Integer page); + + Post_like likePost(Long postId, Long userId); + + void dislikePost(Long postId, Long userId); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 6a4689d..c6723c7 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -1,11 +1,15 @@ package friend.spring.service; import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.apiPayload.handler.CommentHandler; import friend.spring.apiPayload.handler.PostHandler; import friend.spring.apiPayload.handler.UserHandler; +import friend.spring.converter.CommentConverter; import friend.spring.converter.PostConverter; import friend.spring.domain.*; import friend.spring.domain.enums.PostVoteType; +import friend.spring.domain.mapping.Comment_like; +import friend.spring.domain.mapping.Post_like; import friend.spring.repository.*; import friend.spring.web.dto.PollOptionDTO; import friend.spring.web.dto.PostRequestDTO; @@ -32,6 +36,8 @@ public class PostServiceImpl implements PostService{ private final Gauge_PollRepository gaugePollRepository; private final Card_PollRepository cardPollRepository; private final PointRepository pointRepository; + private final PostLikeRepository postLikeRepository; + private final UserService userService; @Override public void checkPost(Boolean flag) { if (!flag) { @@ -53,7 +59,14 @@ public Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user) { } return Boolean.TRUE; } - + + @Override + public void checkPostLike(Boolean flag) { + if (!flag) { + throw new PostHandler(ErrorStatus.POST_LIKE_NOT_FOUND); + } + } + @Override @Transactional public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { @@ -194,4 +207,44 @@ public Page getMyPostList(Long userId, Integer page) { Page userPage = postRepository.findAllByUser(myUser, PageRequest.of(page, 5)); return userPage; } + + @Override + public Post_like likePost(Long postId, Long userId) { + Optional optionalPost = postRepository.findById(postId); + if (optionalPost.isEmpty()) { + this.checkPost(false); + } + + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Post post = optionalPost.get(); + User user = optionalUser.get(); + + Post_like post_like = PostConverter.toPostLike(post, user); + return postLikeRepository.save(post_like); + } + + @Override + public void dislikePost(Long postId, Long userId) { + Optional optionalPost = postRepository.findById(postId); + if (optionalPost.isEmpty()) { + this.checkPost(false); + } + + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Optional optionalPost_like = postLikeRepository.findByPostIdAndUserId(postId, userId); + if (optionalPost_like.isEmpty()) { + this.checkPostLike(false); + } + + Post_like post_like = optionalPost_like.get(); + postLikeRepository.delete(post_like); + } } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 5466826..5595b5a 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -1,14 +1,20 @@ package friend.spring.web.controller; import friend.spring.apiPayload.ApiResponse; +import friend.spring.converter.CommentConverter; import friend.spring.converter.PostConverter; import friend.spring.domain.Post; +import friend.spring.domain.mapping.Comment_like; +import friend.spring.domain.mapping.Post_like; import friend.spring.service.PostService; +import friend.spring.web.dto.CommentResponseDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -41,4 +47,45 @@ public ApiResponse join(@RequestBody @Valid Po Post post= postService.joinPost(request,UserId); return ApiResponse.onSuccess(PostConverter.toAddPostResultDTO(post)); } + + // 글 추천(좋아요) 생성 + @PostMapping("/{post-id}/like") + @Operation(summary = "글 추천(좋아요) 생성 API", description = "글 추천(좋아요) 생성하는 API입니다. ex) /posts/1/like") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + }) + public ApiResponse likePost( + @PathVariable("post-id") Long postId, + @RequestHeader("userId") Long userId + ) { + Post_like post_like = postService.likePost(postId, userId); + return ApiResponse.onSuccess(PostConverter.toPostLikeRes(post_like)); + } + + // 글 추천(좋아요) 해제 + @PostMapping("/{post-id}/like/del") + @Operation(summary = "글 추천(좋아요) 해제 API", description = "글 추천(좋아요) 해제하는 API입니다. ex) /posts/1/like/del") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4003",description = "글에 대한 좋아요 데이터를 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + }) + public ApiResponse dislikePost( + @PathVariable("post-id") Long postId, + @RequestHeader("userId") Long userId + ) { + postService.dislikePost(postId, userId); + return ApiResponse.onSuccess(null); + } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 761e077..1ac9caf 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -23,4 +23,12 @@ public static class MyPostDTO { Integer postLike; Integer comment; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class PostLikeRes { + Long post_like_id; + } } \ No newline at end of file From 28f8d09c880a7431a8a3c6a1df293d8f4d85479d Mon Sep 17 00:00:00 2001 From: park sang woo Date: Sat, 3 Feb 2024 16:25:50 +0900 Subject: [PATCH 106/255] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8,JWT=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 2 +- .../spring/config/RedisRepositoryConfig.java | 41 +++++++ .../spring/config/WebSecurityConfig.java | 1 + .../spring/converter/UserConverter.java | 20 ++- src/main/java/friend/spring/domain/User.java | 6 +- .../friend/spring/domain/enums/RoleType.java | 5 + .../spring/security/JwtTokenProvider.java | 40 +++--- .../friend/spring/service/UserService.java | 9 +- .../spring/service/UserServiceImpl.java | 114 +++++++++++++++++- .../web/controller/UserRestController.java | 25 ++++ .../java/friend/spring/web/dto/TokenDTO.java | 8 +- .../spring/web/dto/UserResponseDTO.java | 22 ++++ 12 files changed, 260 insertions(+), 33 deletions(-) create mode 100644 src/main/java/friend/spring/config/RedisRepositoryConfig.java create mode 100644 src/main/java/friend/spring/domain/enums/RoleType.java diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 68ca9c7..9e81ab5 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -27,7 +27,7 @@ public enum ErrorStatus implements BaseErrorCode { EMPTY_JWT(HttpStatus.BAD_REQUEST, "USER4006", "JWT를 입력해주세요."), INVALID_JWT(HttpStatus.UNAUTHORIZED, "USER4007", "유효하지 않은 JWT입니다."), PASSWORD_INCORRECT(HttpStatus.NOT_FOUND, "USER4008", "비밀번호가 틀렸습니다."), - + RTK_INCORREXT(HttpStatus.UNAUTHORIZED,"USER4100","RefreshToken값을 확인해주세요."), // 글 관련 응답 POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "글을 찾을 수 없습니다."), POST_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "POST4002", "올바른 사용자(글 작성자)가 아닙니다."), diff --git a/src/main/java/friend/spring/config/RedisRepositoryConfig.java b/src/main/java/friend/spring/config/RedisRepositoryConfig.java new file mode 100644 index 0000000..6cb65af --- /dev/null +++ b/src/main/java/friend/spring/config/RedisRepositoryConfig.java @@ -0,0 +1,41 @@ +package friend.spring.config; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@RequiredArgsConstructor +@Configuration +@EnableRedisRepositories +public class RedisRepositoryConfig { + + @Value("${spring.redis.host}") + private String host; + + @Value("${spring.redis.port}") + private int port; + + // lettuce + // RedisConnectionFactory 인터페이스를 통해 LettuceConnectionFactory를 생성하여 반환한다. + // RedisProperties로 yaml에 저장한 host, post를 가지고 와서 연결한다. + @Bean + public RedisConnectionFactory redisConnectionFactory(){ + return new LettuceConnectionFactory(host, port); + } + + // setKeySerializer, setValueSerializer 설정으로 redis-cli를 통해 직접 데이터를 보는게 가능하다. + @Bean + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>();// redisTemplate를 받아와서 set, get, delete + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + return redisTemplate; + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/config/WebSecurityConfig.java b/src/main/java/friend/spring/config/WebSecurityConfig.java index f29183f..b40aac0 100644 --- a/src/main/java/friend/spring/config/WebSecurityConfig.java +++ b/src/main/java/friend/spring/config/WebSecurityConfig.java @@ -45,6 +45,7 @@ protected void configure(HttpSecurity http) throws Exception { .authorizeRequests() //.antMatchers("/users/test").hasRole("USER") .antMatchers("/**").permitAll() +// .antMatchers("/health").authenticated() .anyRequest().permitAll(); http.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider, redisTemplate), UsernamePasswordAuthenticationFilter.class) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index e6ea0ac..d2f8cb0 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -5,24 +5,27 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.enums.Gender; -import friend.spring.web.dto.UserRequestDTO; -import friend.spring.web.dto.UserResponseDTO; +import friend.spring.domain.enums.RoleType; +import friend.spring.security.JwtTokenProvider; +import friend.spring.service.UserService; +import friend.spring.web.dto.*; +import lombok.RequiredArgsConstructor; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import java.time.LocalDate; import java.time.LocalDateTime; -import friend.spring.web.dto.CommentResponseDTO; -import friend.spring.web.dto.PostResponseDTO; import friend.spring.web.dto.UserResponseDTO; import org.springframework.data.domain.Page; import java.util.List; import java.util.stream.Collectors; + public class UserConverter { + public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ return UserResponseDTO.MyPageResDTO.builder() .userPhoto(user.getImage()) @@ -48,7 +51,9 @@ public static UserResponseDTO.JoinResultDTO joinResultDTO(User user){ .build(); } - public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest){ + + + public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest, String pw){ Gender gender = null; @@ -63,9 +68,11 @@ public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest){ gender = Gender.NONE; break; } + + return User.builder() .email(userJoinRequest.getEmail()) - .password(userJoinRequest.getPassword()) + .password(pw) .nickname(userJoinRequest.getNickname()) .gender(gender) .phone(userJoinRequest.getPhone()) @@ -77,6 +84,7 @@ public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest){ .is_deleted(userJoinRequest.is_deleted()) .point(userJoinRequest.getPoint()) .like(userJoinRequest.getLike()) + .role(RoleType.USER) .build(); } diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index d6c0219..a5fb086 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -2,6 +2,7 @@ import friend.spring.domain.common.BaseEntity; import friend.spring.domain.enums.Gender; +import friend.spring.domain.enums.RoleType; import friend.spring.domain.mapping.Comment_like; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; @@ -28,7 +29,7 @@ public class User extends BaseEntity implements UserDetails { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false, length = 20) + @Column(nullable = false, length = 68) private String password; @Email////1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 @@ -72,6 +73,9 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true)//잠시 true private Integer like; + @Enumerated(value = EnumType.STRING) + @Column(nullable = false) + private RoleType role; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "level_id") diff --git a/src/main/java/friend/spring/domain/enums/RoleType.java b/src/main/java/friend/spring/domain/enums/RoleType.java new file mode 100644 index 0000000..1b713e2 --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/RoleType.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum RoleType { + USER +} diff --git a/src/main/java/friend/spring/security/JwtTokenProvider.java b/src/main/java/friend/spring/security/JwtTokenProvider.java index 38bf922..186ed6b 100644 --- a/src/main/java/friend/spring/security/JwtTokenProvider.java +++ b/src/main/java/friend/spring/security/JwtTokenProvider.java @@ -2,6 +2,7 @@ import ch.qos.logback.core.status.ErrorStatus; import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.handler.UserHandler; import friend.spring.domain.User; import friend.spring.repository.UserRepository; import friend.spring.web.dto.TokenDTO; @@ -26,7 +27,7 @@ import java.util.Date; import java.util.Optional; -import static friend.spring.apiPayload.code.status.ErrorStatus.INVALID_JWT; +import static friend.spring.apiPayload.code.status.ErrorStatus.*; @Slf4j @RequiredArgsConstructor @@ -59,10 +60,8 @@ public TokenDTO createAccessToken(String email) { Claims claims = Jwts.claims().setSubject(email); // JWT payload에 저장되는 정보단위 - if(user.isPresent()) { + user.ifPresent(value -> claims.put("id", value.getId())); - claims.put("email", user.get().getEmail()); - } Date now = new Date(); Date expiresTime = new Date(now.getTime() + tokenValidTime); @@ -75,16 +74,20 @@ public TokenDTO createAccessToken(String email) { //.claim("userIdx",user.get().getUserIdx()) //.claim("role", user.get().getRole()) .compact(); + return new TokenDTO(String.valueOf(TokenType.atk), token, expiresTime); } // JWT Refresh 토큰 생성 public TokenDTO createRefreshToken(String email) { // Refresh 토큰 유효시간 2주 - long tokenValidTime = 60 * 60 * 24 * 14 * 1000L; + long tokenValidTime = 30 * 60 * 1000L; + Optional user = userRepository.findByEmail(email); Claims claims = Jwts.claims().setSubject(email); // JWT payload에 저장되는 정보단위 + user.ifPresent(value -> claims.put("id", value.getId())); + Date now = new Date(); Date expiresTime = new Date(now.getTime() + tokenValidTime); // 토큰 만료 시간 String token = Jwts.builder() @@ -148,18 +151,19 @@ public Date getExpireTime(String jwtToken) { Jws claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwtToken); return claims.getBody().getExpiration(); } + // 토큰에서 회원정보 추출 - userIdx 추출 + public Long getCurrentUser(HttpServletRequest request) throws GeneralException { // userIdx 가져오기 + String jwtToken = resolveAccessToken(request); // Request의 header에서 Access 토큰 추출 + if(!validateToken(jwtToken)) { + throw new GeneralException(INVALID_JWT); + } -// // 토큰에서 회원정보 추출 - userIdx 추출 -// public Long getCurrentUser(HttpServletRequest request) throws GeneralException { // userIdx 가져오기 -// String jwtToken = resolveAccessToken(request); // Request의 header에서 Access 토큰 추출 -// if(!validateToken(jwtToken)) { -// throw new (INVALID_JWT); -// } -// Long userIdx = Long.valueOf(String.valueOf(Jwts.parser() -// .setSigningKey(secretKey) -// .parseClaimsJws(jwtToken) -// .getBody() -// .get("userIdx"))); -// return userIdx; -// } + Long userIdx = Long.valueOf(String.valueOf(Jwts.parser() + .setSigningKey(secretKey) + .parseClaimsJws(jwtToken) + .getBody() + .get("id"))); + + return userIdx; + } } diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index a530e7a..f3bec0c 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -2,14 +2,21 @@ import friend.spring.domain.Level; import friend.spring.domain.User; +import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; +import javax.servlet.http.HttpServletRequest; +import java.util.List; + public interface UserService { User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest); - + List login(UserRequestDTO.UserLoginRequest userLoginRequest); User findMyPage(Long id); void checkUser(Boolean flag); Level nextLevel(Long id); + String logout(HttpServletRequest request); + + List reissue(HttpServletRequest request); } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 0cf8fb8..eb89b03 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -1,5 +1,6 @@ package friend.spring.service; +import friend.spring.apiPayload.GeneralException; import friend.spring.converter.UserConverter; import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.domain.Level; @@ -7,14 +8,21 @@ import friend.spring.repository.LevelRepository; import friend.spring.repository.UserRepository; import friend.spring.apiPayload.handler.UserHandler; +import friend.spring.security.JwtTokenProvider; +import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.concurrent.TimeUnit; import static friend.spring.apiPayload.code.status.ErrorStatus.*; @@ -25,8 +33,13 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; - //private final BCryptPasswordEncoder bCryptPasswordEncoder; + private final LevelRepository levelRepository; + private final JwtTokenProvider jwtTokenProvider; + private final RedisTemplate redisTemplate; + + + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @Override public User findMyPage(Long id) { @@ -43,13 +56,22 @@ public void checkUser(Boolean flag) { throw new UserHandler(USER_NOT_FOUND); } } - - public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest) { - User newUser = UserConverter.toUser(userJoinRequest); + public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest) {//회원가입 + Optional user = userRepository.findByEmail(userJoinRequest.getEmail()); + + if (user.isPresent()) { + throw new UserHandler(USER_EXISTS_EMAIL); + } + + + String encodedPw = encoder.encode(userJoinRequest.getPassword()); + + User newUser = UserConverter.toUser(userJoinRequest, encodedPw); return userRepository.saveAndFlush(newUser); } + @Override public Level nextLevel(Long id) { Optional user = userRepository.findById(id); @@ -62,6 +84,90 @@ public Level nextLevel(Long id) { return nxtLevel; } + @Override + public List reissue(HttpServletRequest request) { + String rtk = request.getHeader("rtk"); + System.out.println("reissue함수실행 rtk: "+rtk); + + // refresh token 유효성 검증 + if (!jwtTokenProvider.validateToken(rtk)) + throw new GeneralException(INVALID_JWT); + + String email = jwtTokenProvider.getTokenSub(rtk); + System.out.println("rtk subject인 email: "+email); + + // Redis에서 email 기반으로 저장된 refresh token 값 가져오기 + String refreshToken = (String) redisTemplate.opsForValue().get("RT:" + email); + + if (refreshToken == null) { + throw new GeneralException(RTK_INCORREXT); + } + + if(!refreshToken.equals(rtk)) { + throw new GeneralException(RTK_INCORREXT); + } + + // refresh token 유효할 경우 새로운 토큰 생성 + List tokenDTOList = new ArrayList<>(); + TokenDTO newRefreshToken = jwtTokenProvider.createRefreshToken(email); + TokenDTO newAccessToken = jwtTokenProvider.createAccessToken(email); + tokenDTOList.add(newRefreshToken); + tokenDTOList.add(newAccessToken); + System.out.println("Access Token, Refresh Token 재발행: " +tokenDTOList); + + // Redis에 refresh token 업데이트 + redisTemplate.opsForValue().set("RT:"+email,newRefreshToken.getToken(),newRefreshToken.getTokenExpriresTime().getTime(),TimeUnit.MILLISECONDS); + + return tokenDTOList; + } + + //로그인 + public List login(UserRequestDTO.UserLoginRequest userLoginRequest)throws GeneralException{ + User user = userRepository.findByEmail(userLoginRequest.getEmail()) + .orElseThrow(()-> new GeneralException(USERS_NOT_FOUND_EMAIL));//가입 안된 이메일 + if (!encoder.matches(userLoginRequest.getPassword(), user.getPassword())) { + throw new GeneralException(PASSWORD_INCORRECT); //비밀번호 불일치 + } + //토큰발급 + TokenDTO accessToken = jwtTokenProvider.createAccessToken(user.getEmail()); + TokenDTO refreshToken = jwtTokenProvider.createRefreshToken(user.getEmail()); + + // login 시 Redis에 RT:gominchingy@gmail.com(key): --refresh token실제값--(value) 형태로 refresh 토큰 저장하기 + // opsForValue() : set을 통해 key,value값 저장하고 get(key)통해 value가져올 수 있음. + // refreshToken.getTokenExpriresTime().getTime() : 리프레시 토큰의 만료시간이 지나면 해당 값 자동 삭제 + redisTemplate.opsForValue().set("RT:"+user.getEmail(),refreshToken.getToken(), refreshToken.getTokenExpriresTime().getTime(), TimeUnit.MILLISECONDS); + + List tokenDTOList = new ArrayList<>(); + tokenDTOList.add(accessToken); + tokenDTOList.add(refreshToken); + System.out.println(tokenDTOList); + + return tokenDTOList; + } + + @Override + // 로그아웃 - userIdx + public String logout(HttpServletRequest request) { + + Long userIdx = jwtTokenProvider.getCurrentUser(request); + + System.out.println("getCurrentUser()로 가져온 userIdx : "+userIdx); + User user = userRepository.findById(userIdx) + .orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); + + // Redis 에서 해당 User email 로 저장된 Refresh Token 이 있는지 여부를 확인 후 있을 경우 삭제 + if (redisTemplate.opsForValue().get("RT:" + user.getEmail()) != null) { + // Refresh Token 삭제 + redisTemplate.delete("RT:" + user.getEmail()); + } + // 해당 AccessToken 유효시간 가지고 와서 BlackList 로 저장하기 + String accessToken = jwtTokenProvider.resolveAccessToken(request); + Long expiration = jwtTokenProvider.getExpireTime(accessToken).getTime(); + // Redis 에 --accesstoken--(key) : logout(value) 로 저장, token 만료시간 지나면 자동 삭제 + redisTemplate.opsForValue().set(accessToken, "logout", expiration, TimeUnit.MILLISECONDS); + + return "로그아웃 성공"; + } } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index b2cfd59..1bc41f1 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -1,6 +1,8 @@ package friend.spring.web.controller; import friend.spring.apiPayload.ApiResponse; +import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.converter.UserConverter; import friend.spring.domain.Comment; import friend.spring.domain.Level; @@ -12,6 +14,7 @@ import friend.spring.service.PostService; import friend.spring.service.UserService; import friend.spring.service.UserServiceImpl; +import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; import friend.spring.web.dto.UserResponseDTO; import io.swagger.annotations.Api; @@ -19,7 +22,9 @@ import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; +import java.util.List; @RestController @@ -80,5 +85,25 @@ public ApiResponse join(@RequestBody @Valid UserR return ApiResponse.onSuccess(UserConverter.joinResultDTO(user)); } + + //로그인 + @PostMapping("/login") + public ApiResponse> login(@RequestBody UserRequestDTO.UserLoginRequest userLoginRequest)throws GeneralException{ + List tokenDTOList = userService.login(userLoginRequest); + return ApiResponse.onSuccess(tokenDTOList); + } + + // 토큰 재발급 + @PostMapping("/reissue") + public ApiResponse> reissue(HttpServletRequest request) { + System.out.println("controller: reissue 함수 실행"); + return ApiResponse.onSuccess(userService.reissue(request)); + } + + // 로그아웃 + @PostMapping("/logout") + public ApiResponse logout(HttpServletRequest request) { + return ApiResponse.onSuccess(userService.logout(request)); + } } diff --git a/src/main/java/friend/spring/web/dto/TokenDTO.java b/src/main/java/friend/spring/web/dto/TokenDTO.java index 1b3bd5b..5d51035 100644 --- a/src/main/java/friend/spring/web/dto/TokenDTO.java +++ b/src/main/java/friend/spring/web/dto/TokenDTO.java @@ -1,7 +1,9 @@ package friend.spring.web.dto; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.Getter; import java.util.Date; @@ -9,8 +11,10 @@ @AllArgsConstructor public class TokenDTO { - //1. 로그인 시 토큰을 응답 +// //1. 로그인 시 토큰을 응답 private String types; // atk, rtk - private String token; // jwt 토큰 +// private String token; // jwt 토큰 + private String token; private Date tokenExpriresTime; // 토큰 만료시간 + } \ No newline at end of file diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index d45157b..0a68a93 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -88,6 +88,28 @@ public static class AnswerResDTO { Double adoptCommentPercent; List commentList; } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class LoginResDTO { + + String type; + String accessToken; + String refreshToken; + String tokenExpiresTime; + + + } +// @Getter +// @Builder +// @AllArgsConstructor(access = AccessLevel.PROTECTED) +// @NoArgsConstructor(access = AccessLevel.PROTECTED) +// public static class TokenRefreshResponse { +// +// String accessToken; +// String refreshToken; +// } } \ No newline at end of file From 9398bc8bc6b68081b0ff2f050b22353eecd9e076 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sun, 4 Feb 2024 04:33:06 +0900 Subject: [PATCH 107/255] =?UTF-8?q?#61=20Feat=20:=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/domain/Category.java | 27 +++++++++++++++++++ src/main/java/friend/spring/domain/Post.java | 3 +++ 2 files changed, 30 insertions(+) create mode 100644 src/main/java/friend/spring/domain/Category.java diff --git a/src/main/java/friend/spring/domain/Category.java b/src/main/java/friend/spring/domain/Category.java new file mode 100644 index 0000000..b08d7dd --- /dev/null +++ b/src/main/java/friend/spring/domain/Category.java @@ -0,0 +1,27 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import lombok.*; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Category extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, length = 10) + private String name; + + @Builder.Default + @OneToMany(mappedBy = "category") + private List postList = new ArrayList<>(); +} diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 447f9fe..6e85c70 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -57,6 +57,9 @@ public class Post extends BaseEntity { @JoinColumn(name = "user_id") private User user; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "category_id") + private Category postCategory; // 부모 글 정의 // 고민후기 원글 아이디 @ManyToOne(fetch = FetchType.LAZY) From 9173098785d0904fa9b5d24a3a4dbeb6d1161ffa Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 4 Feb 2024 20:22:07 +0900 Subject: [PATCH 108/255] =?UTF-8?q?#55=20Feat:=20=ED=99=88=20-=20=EC=A7=80?= =?UTF-8?q?=EA=B8=88=20=EA=B0=80=EC=9E=A5=20=ED=95=AB=ED=95=9C=20=EA=B3=A0?= =?UTF-8?q?=EB=AF=BC=ED=88=AC=ED=91=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/aws/s3/AmazonS3Manager.java | 122 ++++++++--------- .../friend/spring/config/AmazonConfig.java | 124 +++++++++--------- .../java/friend/spring/config/S3Config.java | 30 ++--- .../spring/converter/PostConverter.java | 33 +++++ .../spring/converter/UserConverter.java | 13 +- src/main/java/friend/spring/domain/Post.java | 3 + .../repository/CandidateRepository.java | 5 + .../spring/repository/CommentRepository.java | 1 + .../spring/repository/PostLikeRepository.java | 6 +- .../spring/repository/PostRepository.java | 5 + .../friend/spring/service/PostService.java | 3 + .../spring/service/PostServiceImpl.java | 86 +++++++++++- .../java/friend/spring/service/S3Service.java | 58 ++++---- .../web/controller/PostRestController.java | 19 ++- .../spring/web/controller/S3Controller.java | 42 +++--- .../spring/web/dto/PostResponseDTO.java | 23 ++++ .../spring/web/dto/UserResponseDTO.java | 12 +- 17 files changed, 377 insertions(+), 208 deletions(-) diff --git a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java index 5982231..1c32fe3 100644 --- a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java +++ b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java @@ -1,61 +1,61 @@ -//package friend.spring.aws.s3; -// -//import com.amazonaws.services.s3.AmazonS3; -//import com.amazonaws.services.s3.model.ObjectMetadata; -//import friend.spring.config.AmazonConfig; -//import friend.spring.domain.Uuid; -//import friend.spring.repository.UuidRepository; -//import lombok.RequiredArgsConstructor; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.stereotype.Component; -//import org.springframework.web.multipart.MultipartFile; -//import software.amazon.awssdk.core.sync.RequestBody; -//import software.amazon.awssdk.services.s3.S3Client; -//import software.amazon.awssdk.services.s3.model.PutObjectRequest; -// -//import java.io.IOException; -// -//@Slf4j -//@Component -//@RequiredArgsConstructor -//public class AmazonS3Manager{ -// -// private final AmazonS3 amazonS3; -// -// private final S3Client s3Client; -// -// private final AmazonConfig amazonConfig; -// -// private final UuidRepository uuidRepository; -// -// public String uploadFile(String keyName, MultipartFile file){ -// ObjectMetadata metadata = new ObjectMetadata(); -// metadata.setContentLength(file.getSize()); -// try { -// PutObjectRequest putObjectRequest = PutObjectRequest.builder() -// .bucket(amazonConfig.getBucket()) -// .key(keyName) -// .contentType(file.getContentType()) -// .contentDisposition("inline") -// .build(); -// s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(file.getInputStream(), file.getSize())); -// -// }catch (IOException e){ -// log.error("error at AmazonS3Manager uploadFile : {}", (Object) e.getStackTrace()); -// } -// -// return amazonS3.getUrl(amazonConfig.getBucket(), keyName).toString(); -// } -// -// public String generateUserKeyName(Uuid uuid) { -// return amazonConfig.getUserPath() + '/' + uuid.getUuid(); -// } -// -// public String generatePostKeyName(Uuid uuid) { -// return amazonConfig.getPostPath() + '/' + uuid.getUuid(); -// } -// -// public String generateReportKeyName(Uuid uuid) { -// return amazonConfig.getReportPath() + '/' + uuid.getUuid(); -// } -//} \ No newline at end of file +package friend.spring.aws.s3; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.ObjectMetadata; +import friend.spring.config.AmazonConfig; +import friend.spring.domain.Uuid; +import friend.spring.repository.UuidRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; + +import java.io.IOException; + +@Slf4j +@Component +@RequiredArgsConstructor +public class AmazonS3Manager{ + + private final AmazonS3 amazonS3; + + private final S3Client s3Client; + + private final AmazonConfig amazonConfig; + + private final UuidRepository uuidRepository; + + public String uploadFile(String keyName, MultipartFile file){ + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentLength(file.getSize()); + try { + PutObjectRequest putObjectRequest = PutObjectRequest.builder() + .bucket(amazonConfig.getBucket()) + .key(keyName) + .contentType(file.getContentType()) + .contentDisposition("inline") + .build(); + s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(file.getInputStream(), file.getSize())); + + }catch (IOException e){ + log.error("error at AmazonS3Manager uploadFile : {}", (Object) e.getStackTrace()); + } + + return amazonS3.getUrl(amazonConfig.getBucket(), keyName).toString(); + } + + public String generateUserKeyName(Uuid uuid) { + return amazonConfig.getUserPath() + '/' + uuid.getUuid(); + } + + public String generatePostKeyName(Uuid uuid) { + return amazonConfig.getPostPath() + '/' + uuid.getUuid(); + } + + public String generateReportKeyName(Uuid uuid) { + return amazonConfig.getReportPath() + '/' + uuid.getUuid(); + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/config/AmazonConfig.java b/src/main/java/friend/spring/config/AmazonConfig.java index aaca940..a0597eb 100644 --- a/src/main/java/friend/spring/config/AmazonConfig.java +++ b/src/main/java/friend/spring/config/AmazonConfig.java @@ -1,62 +1,62 @@ -//package friend.spring.config; -// -//import com.amazonaws.auth.AWSCredentials; -//import com.amazonaws.auth.AWSCredentialsProvider; -//import com.amazonaws.auth.AWSStaticCredentialsProvider; -//import com.amazonaws.auth.BasicAWSCredentials; -//import com.amazonaws.services.s3.AmazonS3; -//import com.amazonaws.services.s3.AmazonS3ClientBuilder; -//import lombok.Getter; -//import org.springframework.beans.factory.annotation.Value; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -// -//import javax.annotation.PostConstruct; -// -//@Configuration -//@Getter -//public class AmazonConfig { -// -// -// private AWSCredentials awsCredentials; -// -// @Value("${cloud.aws.credentials.accessKey}") -// private String accessKey; -// -// @Value("${cloud.aws.credentials.secretKey}") -// private String secretKey; -// -// @Value("${cloud.aws.region.static}") -// private String region; -// -// @Value("${cloud.aws.s3.bucket}") -// private String bucket; -// -// @Value("${cloud.aws.s3.path.user}") -// private String userPath; -// -// @Value("${cloud.aws.s3.path.post}") -// private String postPath; -// -// @Value("${cloud.aws.s3.path.report}") -// private String reportPath; -// -// @PostConstruct -// public void init() { -// this.awsCredentials = new BasicAWSCredentials(accessKey, secretKey); -// } -// -// @Bean -// public AmazonS3 amazonS3() { -// AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); -// return AmazonS3ClientBuilder.standard() -// .withRegion(region) -// .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) -// .build(); -// } -// -// @Bean -// public AWSCredentialsProvider awsCredentialsProvider() { -// return new AWSStaticCredentialsProvider(awsCredentials); -// } -//} \ No newline at end of file +package friend.spring.config; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; + +@Configuration +@Getter +public class AmazonConfig { + + + private AWSCredentials awsCredentials; + + @Value("${cloud.aws.credentials.accessKey}") + private String accessKey; + + @Value("${cloud.aws.credentials.secretKey}") + private String secretKey; + + @Value("${cloud.aws.region.static}") + private String region; + + @Value("${cloud.aws.s3.bucket}") + private String bucket; + + @Value("${cloud.aws.s3.path.user}") + private String userPath; + + @Value("${cloud.aws.s3.path.post}") + private String postPath; + + @Value("${cloud.aws.s3.path.report}") + private String reportPath; + + @PostConstruct + public void init() { + this.awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + } + + @Bean + public AmazonS3 amazonS3() { + AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + return AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .build(); + } + + @Bean + public AWSCredentialsProvider awsCredentialsProvider() { + return new AWSStaticCredentialsProvider(awsCredentials); + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/config/S3Config.java b/src/main/java/friend/spring/config/S3Config.java index 91adf45..466cced 100644 --- a/src/main/java/friend/spring/config/S3Config.java +++ b/src/main/java/friend/spring/config/S3Config.java @@ -1,15 +1,15 @@ -//package friend.spring.config; -// -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -//import software.amazon.awssdk.regions.Region; -//import software.amazon.awssdk.services.s3.S3Client; -// -//@Configuration -//public class S3Config { -// -// @Bean -// public S3Client defaultS3Client() { -// return S3Client.builder().region(Region.AP_NORTHEAST_2).build(); -// } -//} +package friend.spring.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +@Configuration +public class S3Config { + + @Bean + public S3Client defaultS3Client() { + return S3Client.builder().region(Region.AP_NORTHEAST_2).build(); + } +} diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 46b5b22..b6acda9 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -6,10 +6,12 @@ import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; import friend.spring.domain.mapping.Post_like; +import friend.spring.web.dto.CandidateResponseDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import java.time.LocalDateTime; +import java.util.List; import static friend.spring.domain.enums.PostType.*; @@ -112,6 +114,37 @@ public static PostResponseDTO.PostLikeRes toPostLikeRes(Post_like post_like) { .post_like_id(post_like.getId()) .build(); } + + public static PostResponseDTO.PostSummaryListRes toPostSummaryRes(Post post, Integer like_cnt, Integer comment_cnt, String postVoteType, List candidateSummaryResList) { + Long general_poll_id = null; + Long gauge_poll_id = null; + Long card_poll_id = null; + if (post.getGeneralPoll() != null) { + general_poll_id = post.getGeneralPoll().getId(); + } + if (post.getGaugePoll() != null) { + gauge_poll_id = post.getGaugePoll().getId(); + } + if (post.getCardPoll() != null) { + card_poll_id = post.getCardPoll().getId(); + } + + return PostResponseDTO.PostSummaryListRes.builder() + .title(post.getTitle()) + .content(post.getContent()) + .post_id(post.getId()) + .file(post.getFile()) + .like(like_cnt) + .comment_cnt(comment_cnt) + .created_at(post.getCreatedAt()) + .user(UserConverter.toUserSummaryInfo(post.getUser())) + .postVoteType(postVoteType) + .general_poll_id(general_poll_id) + .gauge_poll_id(gauge_poll_id) + .card_poll_id(card_poll_id) + .candidateList(candidateSummaryResList) + .build(); + } } diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 40f0c68..fe98be1 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -4,11 +4,6 @@ import friend.spring.domain.enums.Gender; import friend.spring.web.dto.*; import friend.spring.domain.enums.RoleType; -import friend.spring.security.JwtTokenProvider; -import friend.spring.service.UserService; -import friend.spring.web.dto.*; -import lombok.RequiredArgsConstructor; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import java.time.LocalDate; import java.time.LocalDateTime; @@ -156,4 +151,12 @@ public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLe .commentList(myCommentDTOList) .build(); } + + public static UserResponseDTO.UserSummaryInfo toUserSummaryInfo(User user) { + return UserResponseDTO.UserSummaryInfo.builder() + .user_id(user.getId()) + .nickname(user.getNickname()) + .image(user.getImage()) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 6e85c70..12515bd 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -53,6 +53,9 @@ public class Post extends BaseEntity { @Column(nullable = true) private Integer point; + @Column(nullable = true) + private String file; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; diff --git a/src/main/java/friend/spring/repository/CandidateRepository.java b/src/main/java/friend/spring/repository/CandidateRepository.java index d04ffa3..2560250 100644 --- a/src/main/java/friend/spring/repository/CandidateRepository.java +++ b/src/main/java/friend/spring/repository/CandidateRepository.java @@ -3,5 +3,10 @@ import friend.spring.domain.Candidate; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface CandidateRepository extends JpaRepository { + List findAllByGeneralPollId(Long general_poll_id); + + List findAllByCardPollId(Long card_poll_id); } diff --git a/src/main/java/friend/spring/repository/CommentRepository.java b/src/main/java/friend/spring/repository/CommentRepository.java index 737bc18..a0a3d31 100644 --- a/src/main/java/friend/spring/repository/CommentRepository.java +++ b/src/main/java/friend/spring/repository/CommentRepository.java @@ -14,4 +14,5 @@ public interface CommentRepository extends JpaRepository { Page findAllByUser(User user, PageRequest pageRequest); + Integer countByPostId(Long postId); } diff --git a/src/main/java/friend/spring/repository/PostLikeRepository.java b/src/main/java/friend/spring/repository/PostLikeRepository.java index b0e6d4b..2fdbacf 100644 --- a/src/main/java/friend/spring/repository/PostLikeRepository.java +++ b/src/main/java/friend/spring/repository/PostLikeRepository.java @@ -1,10 +1,6 @@ package friend.spring.repository; -import friend.spring.domain.Post; -import friend.spring.domain.User; import friend.spring.domain.mapping.Post_like; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; @@ -12,4 +8,6 @@ public interface PostLikeRepository extends JpaRepository { Optional findByPostIdAndUserId(Long postId, Long userId); + + Integer countByPostId(Long postId); } diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index 653b244..af67ca3 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -4,8 +4,13 @@ import friend.spring.domain.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; public interface PostRepository extends JpaRepository { Page findAllByUser(User user, PageRequest pageRequest); + + @Query(value = "SELECT * FROM post WHERE post.created_at >= DATE_ADD(now(), INTERVAL -24 HOUR) ORDER BY post.point DESC", nativeQuery = true) + Page findBestPosts(Pageable pageable); } diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index 25643da..ea69ebe 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -5,6 +5,7 @@ import friend.spring.domain.User; import friend.spring.domain.mapping.Post_like; import friend.spring.web.dto.PostRequestDTO; +import friend.spring.web.dto.PostResponseDTO; import org.springframework.data.domain.Page; public interface PostService { @@ -23,5 +24,7 @@ public interface PostService { Post_like likePost(Long postId, Long userId); void dislikePost(Long postId, Long userId); + + Page getBestPosts(Integer page, Integer size); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index c6723c7..359a24b 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -1,25 +1,25 @@ package friend.spring.service; import friend.spring.apiPayload.code.status.ErrorStatus; -import friend.spring.apiPayload.handler.CommentHandler; import friend.spring.apiPayload.handler.PostHandler; import friend.spring.apiPayload.handler.UserHandler; -import friend.spring.converter.CommentConverter; +import friend.spring.converter.CandidateConverter; import friend.spring.converter.PostConverter; import friend.spring.domain.*; -import friend.spring.domain.enums.PostVoteType; -import friend.spring.domain.mapping.Comment_like; import friend.spring.domain.mapping.Post_like; import friend.spring.repository.*; -import friend.spring.web.dto.PollOptionDTO; -import friend.spring.web.dto.PostRequestDTO; +import friend.spring.web.dto.*; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Optional; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; import static friend.spring.domain.enums.PostType.*; import static friend.spring.domain.enums.PostVoteType.*; @@ -37,6 +37,7 @@ public class PostServiceImpl implements PostService{ private final Card_PollRepository cardPollRepository; private final PointRepository pointRepository; private final PostLikeRepository postLikeRepository; + private final CommentRepository commentRepository; private final UserService userService; @Override public void checkPost(Boolean flag) { @@ -247,4 +248,75 @@ public void dislikePost(Long postId, Long userId) { Post_like post_like = optionalPost_like.get(); postLikeRepository.delete(post_like); } + + @Override + public Page getBestPosts(Integer page, Integer size) { + Pageable pageable = PageRequest.of(page, size); + Page bestPostPage = postRepository.findBestPosts(pageable); + List postResList = bestPostPage + .map(post -> { + Integer like_cnt = postLikeRepository.countByPostId(post.getId()); + Integer comment_cnt = commentRepository.countByPostId(post.getId()); + String postVoteType = null; + Long general_poll_id = null; + Long gauge_poll_id = null; + Long card_poll_id = null; + List candidateList = null; + List candidateSummaryResList = null; + if (post.getVoteType().equals(GENERAL)) { // 일반 투표인 경우 + postVoteType = "GENERAL"; + general_poll_id = post.getGeneralPoll().getId(); + candidateList = candidateRepository.findAllByGeneralPollId(general_poll_id); + candidateSummaryResList = new ArrayList<>(); + + // 총 투표수 계산 + Double totalVotes = (double) post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + for (Candidate candidate : candidateList) { + long selectionCount = candidateSelectionCounts.getOrDefault(candidate.getId(), 0L); + Double percent = (double) selectionCount / totalVotes * 100; + candidateSummaryResList.add(CandidateConverter.toCandidateSummaryRes(candidate, percent)); + } + } else if (post.getVoteType().equals(GAUGE)) { + postVoteType = "GAUGE"; + gauge_poll_id = post.getGaugePoll().getId(); + } else { + postVoteType = "CARD"; + card_poll_id = post.getCardPoll().getId(); + candidateList = candidateRepository.findAllByCardPollId(card_poll_id); + candidateSummaryResList = new ArrayList<>(); + + // 총 투표수 계산 + Double totalVotes = (double) post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + for (Candidate candidate : candidateList) { + long selectionCount = candidateSelectionCounts.getOrDefault(candidate.getId(), 0L); + Double percent = (double) selectionCount / totalVotes * 100; + candidateSummaryResList.add(CandidateConverter.toCandidateSummaryRes(candidate, percent)); + } + } + + PostResponseDTO.PostSummaryListRes postGetRes = PostConverter.toPostSummaryRes(post, like_cnt, comment_cnt, postVoteType, candidateSummaryResList); + return postGetRes; + }) + .filter(Objects::nonNull) // null인 요소는 필터링 + .get() + .collect(Collectors.toList()); + + return new PageImpl<>(postResList, pageable, bestPostPage.getTotalElements()); + } } diff --git a/src/main/java/friend/spring/service/S3Service.java b/src/main/java/friend/spring/service/S3Service.java index 6c6e26b..2c34a8f 100644 --- a/src/main/java/friend/spring/service/S3Service.java +++ b/src/main/java/friend/spring/service/S3Service.java @@ -1,29 +1,29 @@ -//package friend.spring.service; -// -//import friend.spring.aws.s3.AmazonS3Manager; -//import friend.spring.domain.Uuid; -//import friend.spring.repository.UuidRepository; -//import lombok.RequiredArgsConstructor; -//import org.springframework.stereotype.Service; -//import org.springframework.transaction.annotation.Transactional; -//import org.springframework.web.multipart.MultipartFile; -// -//import java.util.UUID; -// -//@Service -//@Transactional -//@RequiredArgsConstructor -//public class S3Service { -// private final UuidRepository uuidRepository; -// private final AmazonS3Manager s3Manager; -// -// // 유저 프로필 사진 올리기인 경우 -// public String uploadUserImage(MultipartFile file) { -// String uuid = UUID.randomUUID().toString(); -// Uuid savedUuid = uuidRepository.save(Uuid.builder() -// .uuid(uuid).build()); -// -// String pictureUrl = s3Manager.uploadFile(s3Manager.generateUserKeyName(savedUuid), file); -// return pictureUrl; -// } -//} +package friend.spring.service; + +import friend.spring.aws.s3.AmazonS3Manager; +import friend.spring.domain.Uuid; +import friend.spring.repository.UuidRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.util.UUID; + +@Service +@Transactional +@RequiredArgsConstructor +public class S3Service { + private final UuidRepository uuidRepository; + private final AmazonS3Manager s3Manager; + + // 유저 프로필 사진 올리기인 경우 + public String uploadUserImage(MultipartFile file) { + String uuid = UUID.randomUUID().toString(); + Uuid savedUuid = uuidRepository.save(Uuid.builder() + .uuid(uuid).build()); + + String pictureUrl = s3Manager.uploadFile(s3Manager.generateUserKeyName(savedUuid), file); + return pictureUrl; + } +} diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 5595b5a..9595755 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -14,7 +14,7 @@ import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; +import org.springframework.data.domain.Page; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -88,4 +88,21 @@ public ApiResponse dislikePost( postService.dislikePost(postId, userId); return ApiResponse.onSuccess(null); } + + // 홈 - 지금 가장 핫한 고민투표 + @GetMapping("/best") + @Operation(summary = "홈 - 지금 가장 핫한 고민투표 API", description = "홈 - 지금 가장 핫한 고민투표 조회 API입니다. ex) /posts/best") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + }) + @Parameters({ + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), + @Parameter(name = "size", description = "query string(RequestParam) - 한 번에 글 몇 개씩 불러올지 개수를 세는 변수 (1 이상 자연수로 설정)") + }) + public ApiResponse> getBestPosts( + @RequestParam(name = "page") Integer page, + @RequestParam(name = "size") Integer size + ) { + return ApiResponse.onSuccess(postService.getBestPosts(page, size)); + } } diff --git a/src/main/java/friend/spring/web/controller/S3Controller.java b/src/main/java/friend/spring/web/controller/S3Controller.java index 478d475..8052453 100644 --- a/src/main/java/friend/spring/web/controller/S3Controller.java +++ b/src/main/java/friend/spring/web/controller/S3Controller.java @@ -1,21 +1,21 @@ -//package friend.spring.web.controller; -// -//import friend.spring.apiPayload.ApiResponse; -//import friend.spring.service.S3Service; -//import lombok.RequiredArgsConstructor; -//import org.springframework.web.bind.annotation.*; -//import org.springframework.web.multipart.MultipartFile; -// -//@RestController -//@RequiredArgsConstructor -//@RequestMapping("/uploadImage") -//public class S3Controller { -// private final S3Service s3Service; -// -// // 유저 이미지 올리기 -// @PostMapping(value = "", consumes = "multipart/form-data") -// public ApiResponse uploadUserImage(@RequestParam("file") MultipartFile file) { -// String url = s3Service.uploadUserImage(file); -// return ApiResponse.onSuccess(url); -// } -//} +package friend.spring.web.controller; + +import friend.spring.apiPayload.ApiResponse; +import friend.spring.service.S3Service; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/uploadImage") +public class S3Controller { + private final S3Service s3Service; + + // 유저 이미지 올리기 + @PostMapping(value = "", consumes = "multipart/form-data") + public ApiResponse uploadUserImage(@RequestParam("file") MultipartFile file) { + String url = s3Service.uploadUserImage(file); + return ApiResponse.onSuccess(url); + } +} diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 1ac9caf..d2782c9 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -2,6 +2,8 @@ import lombok.*; import java.time.LocalDateTime; +import java.util.List; + public class PostResponseDTO { @Builder @Data @@ -31,4 +33,25 @@ public static class MyPostDTO { public static class PostLikeRes { Long post_like_id; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class PostSummaryListRes { + String title; + String content; + Long post_id; + String file; + Integer like; + Integer comment_cnt; + LocalDateTime created_at; + UserResponseDTO.UserSummaryInfo user; + String postVoteType; + Long general_poll_id; + Long gauge_poll_id; + Long card_poll_id; + List candidateList; + } + } \ No newline at end of file diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index 73723ec..24b04ca 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -1,11 +1,8 @@ package friend.spring.web.dto; -import friend.spring.domain.User; import friend.spring.domain.enums.Gender; import lombok.*; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotEmpty; import java.time.LocalDate; import java.util.List; @@ -113,4 +110,13 @@ public static class LoginResDTO { // String refreshToken; // } + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Builder + public static class UserSummaryInfo { + Long user_id; + String nickname; + String image; + } } \ No newline at end of file From b1176fa7cda60069007edbac93c66ebb10a13ad2 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 4 Feb 2024 20:40:39 +0900 Subject: [PATCH 109/255] =?UTF-8?q?#55=20Refactor:=20=ED=99=88=20-=20?= =?UTF-8?q?=EC=A7=80=EA=B8=88=20=EA=B0=80=EC=9E=A5=20=ED=95=AB=ED=95=9C=20?= =?UTF-8?q?=EA=B3=A0=EB=AF=BC=ED=88=AC=ED=91=9C=20=ED=88=AC=ED=91=9C=20id?= =?UTF-8?q?=20=EC=A0=84=EB=8B=AC=EB=B0=A9=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/CandidateConverter.java | 15 +++++++++++++++ .../friend/spring/converter/PostConverter.java | 18 ++++-------------- .../friend/spring/service/PostServiceImpl.java | 2 +- .../spring/web/dto/CandidateResponseDTO.java | 18 ++++++++++++++++++ 4 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 src/main/java/friend/spring/converter/CandidateConverter.java create mode 100644 src/main/java/friend/spring/web/dto/CandidateResponseDTO.java diff --git a/src/main/java/friend/spring/converter/CandidateConverter.java b/src/main/java/friend/spring/converter/CandidateConverter.java new file mode 100644 index 0000000..589ad6b --- /dev/null +++ b/src/main/java/friend/spring/converter/CandidateConverter.java @@ -0,0 +1,15 @@ +package friend.spring.converter; + +import friend.spring.domain.Candidate; +import friend.spring.web.dto.CandidateResponseDTO; + +public class CandidateConverter { + + public static CandidateResponseDTO.CandidateSummaryRes toCandidateSummaryRes(Candidate candidate, Double percent) { + return CandidateResponseDTO.CandidateSummaryRes.builder() + .candidate_id(candidate.getId()) + .candidate_name(candidate.getName()) + .ratio(percent) + .build(); + } +} diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index b6acda9..41b4f4b 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -115,20 +115,10 @@ public static PostResponseDTO.PostLikeRes toPostLikeRes(Post_like post_like) { .build(); } - public static PostResponseDTO.PostSummaryListRes toPostSummaryRes(Post post, Integer like_cnt, Integer comment_cnt, String postVoteType, List candidateSummaryResList) { - Long general_poll_id = null; - Long gauge_poll_id = null; - Long card_poll_id = null; - if (post.getGeneralPoll() != null) { - general_poll_id = post.getGeneralPoll().getId(); - } - if (post.getGaugePoll() != null) { - gauge_poll_id = post.getGaugePoll().getId(); - } - if (post.getCardPoll() != null) { - card_poll_id = post.getCardPoll().getId(); - } - + public static PostResponseDTO.PostSummaryListRes toPostSummaryRes(Post post, Integer like_cnt, Integer comment_cnt, String postVoteType, + List candidateSummaryResList, + Long general_poll_id, Long gauge_poll_id, Long card_poll_id + ) { return PostResponseDTO.PostSummaryListRes.builder() .title(post.getTitle()) .content(post.getContent()) diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 359a24b..3010ce7 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -310,7 +310,7 @@ public Page getBestPosts(Integer page, Integ } } - PostResponseDTO.PostSummaryListRes postGetRes = PostConverter.toPostSummaryRes(post, like_cnt, comment_cnt, postVoteType, candidateSummaryResList); + PostResponseDTO.PostSummaryListRes postGetRes = PostConverter.toPostSummaryRes(post, like_cnt, comment_cnt, postVoteType, candidateSummaryResList, general_poll_id, gauge_poll_id, card_poll_id); return postGetRes; }) .filter(Objects::nonNull) // null인 요소는 필터링 diff --git a/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java b/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java new file mode 100644 index 0000000..6e6b64b --- /dev/null +++ b/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java @@ -0,0 +1,18 @@ +package friend.spring.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class CandidateResponseDTO { + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class CandidateSummaryRes { + Long candidate_id; // 후보 아이디 + String candidate_name; // 후보 이름 + Double ratio; // 비율 + } +} From 6dc4079aec453b2733ff01d3cf662e48e434a24f Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 4 Feb 2024 21:55:21 +0900 Subject: [PATCH 110/255] =?UTF-8?q?#55=20Feat:=20=ED=99=88=20-=20=EB=8B=B5?= =?UTF-8?q?=EB=B3=80=EC=9D=84=20=EA=B8=B0=EB=8B=A4=EB=A6=AC=EB=8A=94=20?= =?UTF-8?q?=EA=B3=A0=EB=AF=BC=EB=93=A4=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B8=80=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=EC=9D=84=20getPostRes=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/repository/PostRepository.java | 2 ++ .../friend/spring/service/PostService.java | 6 ++++++ .../friend/spring/service/PostServiceImpl.java | 18 +++++++++++++++--- .../web/controller/PostRestController.java | 16 ++++++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index af67ca3..30c2182 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -13,4 +13,6 @@ public interface PostRepository extends JpaRepository { @Query(value = "SELECT * FROM post WHERE post.created_at >= DATE_ADD(now(), INTERVAL -24 HOUR) ORDER BY post.point DESC", nativeQuery = true) Page findBestPosts(Pageable pageable); + + Page findAllByOrderByCreatedAtDesc(Pageable pageable); } diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index ea69ebe..ce5e7ca 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -8,6 +8,8 @@ import friend.spring.web.dto.PostResponseDTO; import org.springframework.data.domain.Page; +import java.util.List; + public interface PostService { void checkPost(Boolean flag); @@ -26,5 +28,9 @@ public interface PostService { void dislikePost(Long postId, Long userId); Page getBestPosts(Integer page, Integer size); + + Page getRecentPosts(Integer page, Integer size); + + List getPostRes(Page postPage); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 3010ce7..9706856 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -253,7 +253,21 @@ public void dislikePost(Long postId, Long userId) { public Page getBestPosts(Integer page, Integer size) { Pageable pageable = PageRequest.of(page, size); Page bestPostPage = postRepository.findBestPosts(pageable); - List postResList = bestPostPage + List postResList = getPostRes(bestPostPage); + return new PageImpl<>(postResList, pageable, bestPostPage.getTotalElements()); + } + + @Override + public Page getRecentPosts(Integer page, Integer size) { + Pageable pageable = PageRequest.of(page, size); + Page recentPostPage = postRepository.findAllByOrderByCreatedAtDesc(pageable); + List postResList = getPostRes(recentPostPage); + return new PageImpl<>(postResList, pageable, recentPostPage.getTotalElements()); + } + + @Override + public List getPostRes(Page postPage) { + return postPage .map(post -> { Integer like_cnt = postLikeRepository.countByPostId(post.getId()); Integer comment_cnt = commentRepository.countByPostId(post.getId()); @@ -316,7 +330,5 @@ public Page getBestPosts(Integer page, Integ .filter(Objects::nonNull) // null인 요소는 필터링 .get() .collect(Collectors.toList()); - - return new PageImpl<>(postResList, pageable, bestPostPage.getTotalElements()); } } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 9595755..16793de 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -105,4 +105,20 @@ public ApiResponse> getBestPosts( ) { return ApiResponse.onSuccess(postService.getBestPosts(page, size)); } + + @GetMapping("/recent") + @Operation(summary = "홈 - 답변을 기다리는 고민들 API", description = "홈 - 답변을 기다리는 고민들 조회 API입니다. ex) /posts/recent") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + }) + @Parameters({ + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), + @Parameter(name = "size", description = "query string(RequestParam) - 한 번에 글 몇 개씩 불러올지 개수를 세는 변수 (1 이상 자연수로 설정)") + }) + public ApiResponse> getRecentPosts( + @RequestParam(name = "page") Integer page, + @RequestParam(name = "size") Integer size + ) { + return ApiResponse.onSuccess(postService.getRecentPosts(page, size)); + } } From 53d718473ec0edeb5422f5e2896df4b880ef6166 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 5 Feb 2024 00:18:35 +0900 Subject: [PATCH 111/255] =?UTF-8?q?#65=20Refactor:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=95=84=EC=9B=83,=20=ED=86=A0=ED=81=B0=EC=9E=AC=EB=B0=9C?= =?UTF-8?q?=EA=B8=89=20RequestHeader=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/PostRestController.java | 42 +++++++++++++++++++ .../web/controller/UserRestController.java | 4 +- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 16793de..4c76e9b 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -106,6 +106,7 @@ public ApiResponse> getBestPosts( return ApiResponse.onSuccess(postService.getBestPosts(page, size)); } + // 홈 - 답변을 기다리는 고민들 @GetMapping("/recent") @Operation(summary = "홈 - 답변을 기다리는 고민들 API", description = "홈 - 답변을 기다리는 고민들 조회 API입니다. ex) /posts/recent") @ApiResponses({ @@ -121,4 +122,45 @@ public ApiResponse> getRecentPosts( ) { return ApiResponse.onSuccess(postService.getRecentPosts(page, size)); } + +// // 스크랩 추가 +// @PostMapping("/{post-id}/scrap") +// @Operation(summary = "스크랩 추가 API", description = "스크랩 추가하는 API입니다. ex) /posts/1/like") +// @ApiResponses({ +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), +// }) +// @Parameters({ +// @Parameter(name = "post-id", description = "path variable - 글 아이디"), +// @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), +// }) +// public ApiResponse createScrapPost( +// @PathVariable("post-id") Long postId, +// @RequestHeader("userId") Long userId +// ) { +// Post_like post_like = postService.likePost(postId, userId); +// return ApiResponse.onSuccess(PostConverter.toPostLikeRes(post_like)); +// } +// +// // 스크랩 해제 +// @PostMapping("/{post-id}/like/del") +// @Operation(summary = "글 추천(좋아요) 해제 API", description = "글 추천(좋아요) 해제하는 API입니다. ex) /posts/1/like/del") +// @ApiResponses({ +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4003",description = "글에 대한 좋아요 데이터를 찾을 수 없습니다."), +// }) +// @Parameters({ +// @Parameter(name = "post-id", description = "path variable - 글 아이디"), +// @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), +// }) +// public ApiResponse deleteScrapPost( +// @PathVariable("post-id") Long postId, +// @RequestHeader("userId") Long userId +// ) { +// postService.dislikePost(postId, userId); +// return ApiResponse.onSuccess(null); +// } } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 7a0fce0..16d0261 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -101,14 +101,14 @@ public ApiResponse> login(@RequestBody UserRequestDTO.UserLoginRe // 토큰 재발급 @PostMapping("/reissue") - public ApiResponse> reissue(HttpServletRequest request) { + public ApiResponse> reissue(@RequestHeader(name = "rtk") String rtk, HttpServletRequest request) { System.out.println("controller: reissue 함수 실행"); return ApiResponse.onSuccess(userService.reissue(request)); } // 로그아웃 @PostMapping("/logout") - public ApiResponse logout(HttpServletRequest request) { + public ApiResponse logout(@RequestHeader(name = "atk") String atk, HttpServletRequest request) { return ApiResponse.onSuccess(userService.logout(request)); } } From ec544cbde05d87971c3b6dde3a70761764018a10 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 5 Feb 2024 00:55:47 +0900 Subject: [PATCH 112/255] =?UTF-8?q?#67=20Feat:=20=EA=B8=80=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=9E=A9=20=EC=B6=94=EA=B0=80/=ED=95=B4=EC=A0=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 3 +- .../spring/converter/PostConverter.java | 14 ++++ .../repository/PostScrapRepository.java | 11 +++ .../friend/spring/service/PostService.java | 8 ++ .../spring/service/PostServiceImpl.java | 56 +++++++++++++ .../web/controller/PostRestController.java | 84 ++++++++++--------- .../spring/web/dto/PostResponseDTO.java | 7 ++ 7 files changed, 142 insertions(+), 41 deletions(-) create mode 100644 src/main/java/friend/spring/repository/PostScrapRepository.java diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 52a9407..0163d9c 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -32,6 +32,7 @@ public enum ErrorStatus implements BaseErrorCode { POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "글을 찾을 수 없습니다."), POST_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "POST4002", "올바른 사용자(글 작성자)가 아닙니다."), POST_LIKE_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4003", "글에 대한 좋아요 데이터를 찾을 수 없습니다."), + POST_SCRAP_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4004", "글에 대한 스크랩 데이터를 찾을 수 없습니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), @@ -41,7 +42,7 @@ public enum ErrorStatus implements BaseErrorCode { COMMENT_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "COMMENT4005", "올바른 사용자(댓글 작성자)가 아닙니다."), // 알림 관련 응답 - ALARM_NOT_FOUND(HttpStatus.NOT_FOUND, "ALARM4001", "알림이 없습니다") + ALARM_NOT_FOUND(HttpStatus.NOT_FOUND, "ALARM4001", "알림이 없습니다"), ; diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 41b4f4b..186d874 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -6,6 +6,7 @@ import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; import friend.spring.domain.mapping.Post_like; +import friend.spring.domain.mapping.Post_scrap; import friend.spring.web.dto.CandidateResponseDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; @@ -135,6 +136,19 @@ public static PostResponseDTO.PostSummaryListRes toPostSummaryRes(Post post, Int .candidateList(candidateSummaryResList) .build(); } + + public static Post_scrap toPostScrap(Post post, User user) { + return Post_scrap.builder() + .post(post) + .user(user) + .build(); + } + + public static PostResponseDTO.ScrapCreateRes toScrapCreateRes(Post_scrap post_scrap) { + return PostResponseDTO.ScrapCreateRes.builder() + .post_scrap_id(post_scrap.getId()) + .build(); + } } diff --git a/src/main/java/friend/spring/repository/PostScrapRepository.java b/src/main/java/friend/spring/repository/PostScrapRepository.java new file mode 100644 index 0000000..ffaa8d6 --- /dev/null +++ b/src/main/java/friend/spring/repository/PostScrapRepository.java @@ -0,0 +1,11 @@ +package friend.spring.repository; + +import friend.spring.domain.mapping.Post_scrap; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface PostScrapRepository extends JpaRepository { + + Optional findByPostIdAndUserId(Long postId, Long userId); +} diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index ce5e7ca..7a2b82c 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -4,10 +4,12 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.mapping.Post_like; +import friend.spring.domain.mapping.Post_scrap; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import org.springframework.data.domain.Page; +import javax.servlet.http.HttpServletRequest; import java.util.List; public interface PostService { @@ -27,10 +29,16 @@ public interface PostService { void dislikePost(Long postId, Long userId); + void checkPostScrap(Boolean flag); + Page getBestPosts(Integer page, Integer size); Page getRecentPosts(Integer page, Integer size); List getPostRes(Page postPage); + + Post_scrap createScrapPost(Long postId, HttpServletRequest request); + + void deleteScrapPost(Long postId, HttpServletRequest request); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 9706856..afd83b9 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -7,7 +7,9 @@ import friend.spring.converter.PostConverter; import friend.spring.domain.*; import friend.spring.domain.mapping.Post_like; +import friend.spring.domain.mapping.Post_scrap; import friend.spring.repository.*; +import friend.spring.security.JwtTokenProvider; import friend.spring.web.dto.*; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -17,6 +19,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.servlet.http.HttpServletRequest; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -38,7 +41,9 @@ public class PostServiceImpl implements PostService{ private final PointRepository pointRepository; private final PostLikeRepository postLikeRepository; private final CommentRepository commentRepository; + private final PostScrapRepository postScrapRepository; private final UserService userService; + private final JwtTokenProvider jwtTokenProvider; @Override public void checkPost(Boolean flag) { if (!flag) { @@ -68,6 +73,13 @@ public void checkPostLike(Boolean flag) { } } + @Override + public void checkPostScrap(Boolean flag) { + if (!flag) { + throw new PostHandler(ErrorStatus.POST_SCRAP_NOT_FOUND); + } + } + @Override @Transactional public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { @@ -331,4 +343,48 @@ public List getPostRes(Page postPage) .get() .collect(Collectors.toList()); } + + @Override + public Post_scrap createScrapPost(Long postId, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + + Optional optionalPost = postRepository.findById(postId); + if (optionalPost.isEmpty()) { + this.checkPost(false); + } + + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Post post = optionalPost.get(); + User user = optionalUser.get(); + + Post_scrap post_scrap = PostConverter.toPostScrap(post, user); + return postScrapRepository.save(post_scrap); + } + + @Override + public void deleteScrapPost(Long postId, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + + Optional optionalPost = postRepository.findById(postId); + if (optionalPost.isEmpty()) { + this.checkPost(false); + } + + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Optional optionalPost_scrap = postScrapRepository.findByPostIdAndUserId(postId, userId); + if (optionalPost_scrap.isEmpty()) { + this.checkPostScrap(false); + } + + Post_scrap post_scrap = optionalPost_scrap.get(); + postScrapRepository.delete(post_scrap); + } } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 4c76e9b..d1d7218 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -5,6 +5,7 @@ import friend.spring.domain.Post; import friend.spring.domain.mapping.Comment_like; import friend.spring.domain.mapping.Post_like; +import friend.spring.domain.mapping.Post_scrap; import friend.spring.service.PostService; import friend.spring.web.dto.CommentResponseDTO; import friend.spring.web.dto.PostRequestDTO; @@ -18,6 +19,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; @RestController @RequiredArgsConstructor @@ -123,44 +125,46 @@ public ApiResponse> getRecentPosts( return ApiResponse.onSuccess(postService.getRecentPosts(page, size)); } -// // 스크랩 추가 -// @PostMapping("/{post-id}/scrap") -// @Operation(summary = "스크랩 추가 API", description = "스크랩 추가하는 API입니다. ex) /posts/1/like") -// @ApiResponses({ -// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), -// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), -// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), -// }) -// @Parameters({ -// @Parameter(name = "post-id", description = "path variable - 글 아이디"), -// @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), -// }) -// public ApiResponse createScrapPost( -// @PathVariable("post-id") Long postId, -// @RequestHeader("userId") Long userId -// ) { -// Post_like post_like = postService.likePost(postId, userId); -// return ApiResponse.onSuccess(PostConverter.toPostLikeRes(post_like)); -// } -// -// // 스크랩 해제 -// @PostMapping("/{post-id}/like/del") -// @Operation(summary = "글 추천(좋아요) 해제 API", description = "글 추천(좋아요) 해제하는 API입니다. ex) /posts/1/like/del") -// @ApiResponses({ -// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), -// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), -// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), -// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4003",description = "글에 대한 좋아요 데이터를 찾을 수 없습니다."), -// }) -// @Parameters({ -// @Parameter(name = "post-id", description = "path variable - 글 아이디"), -// @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), -// }) -// public ApiResponse deleteScrapPost( -// @PathVariable("post-id") Long postId, -// @RequestHeader("userId") Long userId -// ) { -// postService.dislikePost(postId, userId); -// return ApiResponse.onSuccess(null); -// } + // 글 스크랩 추가 + @PostMapping("/{post-id}/scrap") + @Operation(summary = "글 스크랩 추가 API", description = "글 스크랩 추가하는 API입니다. ex) /posts/1/scrap") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) + public ApiResponse createScrapPost( + @PathVariable("post-id") Long postId, + @RequestHeader(name = "atk") String atk, + HttpServletRequest request + ) { + Post_scrap post_scrap = postService.createScrapPost(postId, request); + return ApiResponse.onSuccess(PostConverter.toScrapCreateRes(post_scrap)); + } + + // 글 스크랩 해제 + @PostMapping("/{post-id}/scrap/del") + @Operation(summary = "글 스크랩 해제 API", description = "글 스크랩 해제하는 API입니다. ex) /posts/1/scrap/del") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004",description = "글에 대한 스크랩 데이터를 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) + public ApiResponse deleteScrapPost( + @PathVariable("post-id") Long postId, + @RequestHeader(name = "atk") String atk, + HttpServletRequest request + ) { + postService.deleteScrapPost(postId, request); + return ApiResponse.onSuccess(null); + } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index d2782c9..05ab350 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -54,4 +54,11 @@ public static class PostSummaryListRes { List candidateList; } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ScrapCreateRes { + Long post_scrap_id; + } } \ No newline at end of file From ccb4ca21ff3b8e961152177477f2e001d55ba162 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 5 Feb 2024 05:54:45 +0900 Subject: [PATCH 113/255] =?UTF-8?q?#48=20Feat:=20=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20=EC=99=84=EC=84=B1(=EB=A6=AC=EB=B7=B0?= =?UTF-8?q?=EA=B8=80=20=ED=8F=AC=ED=95=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 115 ++++++++++++++++-- src/main/java/friend/spring/domain/User.java | 3 +- .../spring/service/PostQueryService.java | 2 + .../spring/service/PostQueryServiceImpl.java | 7 ++ .../web/controller/PostRestController.java | 3 +- .../friend/spring/web/dto/ParentPollDTO.java | 14 +++ .../friend/spring/web/dto/ParentPostDTO.java | 23 ++++ .../spring/web/dto/PostResponseDTO.java | 2 +- 8 files changed, 158 insertions(+), 11 deletions(-) create mode 100644 src/main/java/friend/spring/web/dto/ParentPollDTO.java create mode 100644 src/main/java/friend/spring/web/dto/ParentPostDTO.java diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 4ff400f..e98134c 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -4,14 +4,12 @@ import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; -import friend.spring.web.dto.PollOptionDTO; -import friend.spring.web.dto.PostRequestDTO; -import friend.spring.web.dto.PostResponseDTO; +import friend.spring.service.PostQueryService; +import friend.spring.service.PostQueryServiceImpl; +import friend.spring.web.dto.*; import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -19,6 +17,7 @@ public class PostConverter { + private static PostQueryService postQueryService; public static PostResponseDTO.AddPostResultDTO toAddPostResultDTO(Post post) { return PostResponseDTO.AddPostResultDTO.builder() .postId(post.getId()) @@ -32,7 +31,107 @@ public static PollOptionDTO toPollOptionDTO(Candidate candidate){ .optionImg(candidate.getImage()).build(); } + public static ParentPostDTO toParentPostDTO(Post parentPost){ + ParentPollDTO parentPollDTO=null; + Integer parentLikes =parentPost.getPostLikeList().size(); + Integer parentComments= parentPost.getCommentList().size(); + if(parentPost.getVoteType()==PostVoteType.GAUGE) { + return ParentPostDTO.builder() + .nickname(parentPost.getUser().getNickname()) + .title(parentPost.getTitle()) + .content(parentPost.getContent()) + .gauge(parentPost.getGaugePoll().getGauge()) + .like(parentLikes) + .comment(parentComments) + .build(); + } + + if(parentPost.getVoteType()==PostVoteType.GENERAL) { + List pollOptionDTOList = parentPost.getGeneralPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + + // 총 투표수 계산 + long totalVotes = parentPost.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = parentPost.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + // 선택률 -> ParentPollDTO 객체 리스트로 변환 + List candidateInfos = candidateSelectionCounts.entrySet().stream() + .map(entry -> ParentPollDTO.builder() + .candidateId(entry.getKey()) + .rate((int) ((double) entry.getValue() / totalVotes * 100)) + .selection(entry.getValue()) + .build()) + .collect(Collectors.toList()); + + // 선택률이 가장 높은 후보 찾기 + Optional highestSelectionCandidate = candidateInfos.stream() + .max(Comparator.comparingInt(ParentPollDTO::getRate)); + + // 1등 후보의 정보를 ParentPollDTO 객체로 반환 + if(highestSelectionCandidate.isPresent()) { + parentPollDTO = highestSelectionCandidate.get(); + } + + + return ParentPostDTO.builder() + .nickname(parentPost.getUser().getNickname()) + .title(parentPost.getTitle()) + .content(parentPost.getContent()) + .pollOption(pollOptionDTOList) + .pollContent(parentPollDTO) + .like(parentLikes) + .comment(parentComments) + .build(); + } + + List pollOptionDTOList = parentPost.getCardPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + + // 총 투표수 계산 + long totalVotes = parentPost.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = parentPost.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + // 선택률 -> ParentPollDTO 객체 리스트로 변환 + List candidateInfos = candidateSelectionCounts.entrySet().stream() + .map(entry -> ParentPollDTO.builder() + .candidateId(entry.getKey()) + .rate((int) ((double) entry.getValue() / totalVotes * 100)) + .selection(entry.getValue()) + .build()) + .collect(Collectors.toList()); + + // 선택률이 가장 높은 후보 찾기 + Optional highestSelectionCandidate = candidateInfos.stream() + .max(Comparator.comparingInt(ParentPollDTO::getRate)); + + // 1등 후보의 정보를 ParentPollDTO 객체로 반환 + parentPollDTO = highestSelectionCandidate.get(); + + + return ParentPostDTO.builder() + .nickname(parentPost.getUser().getNickname()) + .title(parentPost.getTitle()) + .content(parentPost.getContent()) + .pollOption(pollOptionDTOList) + .pollContent(parentPollDTO) + .like(parentLikes) + .comment(parentComments) + .build(); + + } public static Post toPost(PostRequestDTO.AddPostDTO request) { PostType postType=null; @@ -102,7 +201,7 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { .build(); } - public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, Boolean engage,Long userId){ + public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, Boolean engage,Long userId, Post parentPost){ Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); List userChoiceList=null; @@ -117,7 +216,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .parentId(post.getParentPost().getId()) + .parentPost(toParentPostDTO(parentPost)) .view(post.getView()) .like(likeCount) .comment(commentCount) diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 130bcb4..3e40c16 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -56,7 +56,8 @@ public class User extends BaseEntity { private Boolean is_deleted; @Column(nullable = true) - private Integer point; + @Builder.Default + private Integer point=0; @Column(nullable = true) private String kakao; diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index 94d8904..444cd69 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -7,4 +7,6 @@ public interface PostQueryService { Optional getPostDetail(Long postId); Boolean checkEngage(Long userId, Long postId); + + Post ParentPost(Long parentid); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 96c4866..36a0a3e 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -65,4 +65,11 @@ public Boolean checkEngage(Long postId,Long userId){ } return false; } + + @Override + @Transactional + public Post ParentPost(Long parentid){ + Optional parentPostOptional=postRepository.findById(parentid); + return parentPostOptional.get().getParentPost(); + } } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 7800a48..6c9c99c 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -54,10 +54,11 @@ public ApiResponse join(@RequestBody @Valid Po public ApiResponse getPostDetail(@PathVariable(name="post-id")Long PostId, @PathVariable(name="user-id")Long userId){ Optional postOptional =postQueryService.getPostDetail(PostId); + Post parentPost=postQueryService.ParentPost(PostId);; // Optional postOptional =postRepository.findById(PostId); Boolean engage=postQueryService.checkEngage(PostId,userId); Post post = postOptional.get(); - return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage,userId)); + return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage,userId,parentPost)); } } diff --git a/src/main/java/friend/spring/web/dto/ParentPollDTO.java b/src/main/java/friend/spring/web/dto/ParentPollDTO.java new file mode 100644 index 0000000..eee0dd5 --- /dev/null +++ b/src/main/java/friend/spring/web/dto/ParentPollDTO.java @@ -0,0 +1,14 @@ +package friend.spring.web.dto; + +import lombok.*; + +@Getter +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ParentPollDTO{ + Long candidateId; + Integer rate; + Long selection; +} diff --git a/src/main/java/friend/spring/web/dto/ParentPostDTO.java b/src/main/java/friend/spring/web/dto/ParentPostDTO.java new file mode 100644 index 0000000..c34bc3b --- /dev/null +++ b/src/main/java/friend/spring/web/dto/ParentPostDTO.java @@ -0,0 +1,23 @@ +package friend.spring.web.dto; + +import lombok.*; + +import java.util.List; + +@Getter +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ParentPostDTO { + String nickname; + String title; + String content; + List pollOption; + ParentPollDTO pollContent; + Integer gauge; + Integer like; + Integer comment; +} + + diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index b714676..a588816 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -32,7 +32,7 @@ public static class PostDetailResponse { List pollOption; // 투표글에서만 사용, 후기글에서는 null Integer gauge; // 게이지 투표글에서만 사용, 후기글에서는 null Integer point; // 투표글에서만 사용, 후기글에서는 null - Long parentId; // 후기글에서만 사용, 일반글에서는 null + ParentPostDTO parentPost; // 후기글에서만 사용, 일반글에서는 null Timestamp deadline; // 투표글에서만 사용, 후기글에서는 null List userVote; // 투표글에서 사용자가 투표완료시 투표한 후보 List percent; // 투표글에서 사용자가 투표 완료시 투표한 후보 선택 퍼센트 From 446eb6522dcdcd222b8e750b40624278b78df9c0 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 5 Feb 2024 17:14:38 +0900 Subject: [PATCH 114/255] =?UTF-8?q?#68=20Feat:=20=EA=B8=80=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EB=B3=B4=EA=B8=B0(=ED=9B=84=EA=B8=B0=EA=B8=80=20?= =?UTF-8?q?=EB=AF=B8=EC=99=84=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 152 ++++++++++++++++++ .../spring/service/PostQueryService.java | 5 + .../spring/service/PostQueryServiceImpl.java | 15 ++ .../web/controller/PostRestController.java | 15 ++ .../spring/web/dto/PostResponseDTO.java | 44 +++++ 5 files changed, 231 insertions(+) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index e98134c..93571b4 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -7,6 +7,7 @@ import friend.spring.service.PostQueryService; import friend.spring.service.PostQueryServiceImpl; import friend.spring.web.dto.*; +import org.springframework.data.domain.Page; import java.time.LocalDateTime; import java.util.*; @@ -366,6 +367,157 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .comment(commentCount) .build(); } + + public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Long userId){ + if(post.getPostType()==REVIEW){ + return PostResponseDTO.PollPostGetResponse.builder() + .nickname(post.getUser().getNickname()) + .content(Long.toString(post.getId())) + .build(); + } + if(post.getPostType()==VOTE&&post.getVoteType()==null){ + return PostResponseDTO.PollPostGetResponse.builder() + .nickname(post.getUser().getNickname()) + .content(Long.toString(post.getId())) + .build(); + } + + System.out.println("Post: " + post.getId() + ", UserId: " + userId); + + if (post == null || userId == null) { + throw new IllegalArgumentException("Post or userId cannot be null"); + } + + Integer likeCount = post.getPostLikeList().size(); + Integer commentCount = post.getCommentList().size(); + List userChoiceList=null; + Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + Boolean engage=false; + + if(post.getVoteType()==PostVoteType.GENERAL) { + List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + if(!post.getGeneralPoll().getGeneralVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()){ + engage=true; + } + if(engage) { + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionDTO) + .collect(Collectors.toList()); + + return PostResponseDTO.PollPostGetResponse.builder() + .nickname(post.getUser().getNickname()) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .pollOption(pollOptionDTOList) + .userVote(userChoiceList) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + + } + return PostResponseDTO.PollPostGetResponse.builder() + .nickname(post.getUser().getNickname()) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .pollOption(pollOptionDTOList) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + } + if(post.getVoteType()==PostVoteType.GAUGE){ + if(!post.getGaugePoll().getGaugeVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()){ + engage=true; + } + if(engage) { + return PostResponseDTO.PollPostGetResponse.builder() + .nickname(post.getUser().getNickname()) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .gauge(post.getGaugePoll().getGauge()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + } + return PostResponseDTO.PollPostGetResponse.builder() + .nickname(post.getUser().getNickname()) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + } + List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + System.out.println("fuck"); + if(!post.getCardPoll().getCardVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()){ + engage=true; + } + if(engage) { + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionDTO) + .collect(Collectors.toList()); + + return PostResponseDTO.PollPostGetResponse.builder() + .nickname(post.getUser().getNickname()) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .pollOption(pollOptionDTOList) + .userVote(userChoiceList) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + + } + return PostResponseDTO.PollPostGetResponse.builder() + .nickname(post.getUser().getNickname()) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .pollOption(pollOptionDTOList) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + } + + public static PostResponseDTO.PollPostGetListDTO pollPostGetListDTO(Page postList,Long userId){ + List pollPostGetListDTO = postList.stream() + .map(post->pollPostGetResponse(post,userId)).collect(Collectors.toList()); + return PostResponseDTO.PollPostGetListDTO.builder() + .pollPostList(pollPostGetListDTO) + .isEnd(postList.isLast()) + .build(); + } } diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index 444cd69..64814f8 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -1,6 +1,7 @@ package friend.spring.service; import friend.spring.domain.Post; +import org.springframework.data.domain.Page; import java.util.Optional; @@ -9,4 +10,8 @@ public interface PostQueryService { Boolean checkEngage(Long userId, Long postId); Post ParentPost(Long parentid); + + Optional findPost(Long postId); + + Page getPostList(Integer page,Integer size); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 36a0a3e..ad51d87 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -7,6 +7,9 @@ import friend.spring.repository.*; import friend.spring.web.dto.PostResponseDTO; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -72,4 +75,16 @@ public Post ParentPost(Long parentid){ Optional parentPostOptional=postRepository.findById(parentid); return parentPostOptional.get().getParentPost(); } + + @Override + public Optional findPost(Long postId) { + return Optional.empty(); + } + + @Override + @Transactional + public Page getPostList(Integer page,Integer size){ + return postRepository.findAll(PageRequest.of(page,size, Sort.by(Sort.Direction.ASC,"createdAt"))); + } + } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 6c9c99c..d8ec4db 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -61,4 +62,18 @@ public ApiResponse getPostDetail(@PathVariab return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage,userId,parentPost)); } + @GetMapping("/{user-id}") + @Operation(summary = "글 전체 보기 API", description = "글 전체 보기합니다") + @Parameters({ + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), + @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)") + }) + public ApiResponse getPostDetail( + @RequestParam(name = "page", defaultValue = "0") Integer page, + @RequestParam(name = "size",defaultValue = "15") Integer size, + @RequestParam(name = "user-id") Long userId){ + Page postPage=postQueryService.getPostList(page,size); + return ApiResponse.onSuccess(PostConverter.pollPostGetListDTO(postPage,userId)); + + } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index a588816..02033a8 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -5,6 +5,7 @@ import lombok.Data; import lombok.NoArgsConstructor; +import java.sql.Time; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.List; @@ -42,4 +43,47 @@ public static class PostDetailResponse { Integer comment; } + + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class PollPostGetListDTO{ + List pollPostList; + private Boolean isEnd; + } + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class PollPostGetResponse{ + String nickname; + String title; + String content; + LocalDateTime uploadDate; + List pollOption; + List userVote; + Integer gauge; + Integer like; + Integer comment; + Boolean isLike; + Boolean isComment; + } + + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class ReviewPostGetResponse{ + String nickname; + String title; + String content; + Timestamp uploadDate; + String pollOption; + Integer gauge; + Integer like; + Integer comment; + Boolean isLike; + Boolean isComment; + } } \ No newline at end of file From f6a904dd54f8f93f5e2a2be17bf870ab856db3c4 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 5 Feb 2024 19:25:09 +0900 Subject: [PATCH 115/255] =?UTF-8?q?#69=20Feat:=20=ED=9B=84=EA=B8=B0?= =?UTF-8?q?=EA=B8=80=20=EC=A0=84=EC=B2=B4=20=EB=B3=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 48 ++++++++++++++----- src/main/java/friend/spring/domain/Post.java | 3 ++ .../spring/repository/PostRepository.java | 4 ++ .../spring/service/PostQueryService.java | 4 ++ .../spring/service/PostQueryServiceImpl.java | 17 ++++++- .../web/controller/PostRestController.java | 27 ++++++++--- .../friend/spring/web/dto/PostRequestDTO.java | 6 ++- .../spring/web/dto/PostResponseDTO.java | 14 ++++-- 8 files changed, 100 insertions(+), 23 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 93571b4..9d57814 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -193,6 +193,7 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { return Post.builder() .title(request.getTitle()) .content(request.getContent()) + .file(request.getFile()) .postType(postType) .category(category) .voteType(postVoteType) @@ -217,6 +218,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) + .file(post.getFile()) .parentPost(toParentPostDTO(parentPost)) .view(post.getView()) .like(likeCount) @@ -232,6 +234,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) + .file(post.getFile()) .gauge(value) .point(post.getPoint()) .deadline(post.getGaugePoll().getDeadline()) @@ -292,6 +295,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) + .file(post.getFile()) .pollTitle(post.getGeneralPoll().getPollTitle()) .pollOption(pollOptionDTOList) .point(post.getPoint()) @@ -355,6 +359,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) + .file(post.getFile()) .pollTitle(post.getCardPoll().getPollTitle()) .pollOption(pollOptionDTOList) .point(post.getPoint()) @@ -369,12 +374,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B } public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Long userId){ - if(post.getPostType()==REVIEW){ - return PostResponseDTO.PollPostGetResponse.builder() - .nickname(post.getUser().getNickname()) - .content(Long.toString(post.getId())) - .build(); - } + //로컬 db test if(post.getPostType()==VOTE&&post.getVoteType()==null){ return PostResponseDTO.PollPostGetResponse.builder() .nickname(post.getUser().getNickname()) @@ -382,12 +382,6 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .build(); } - System.out.println("Post: " + post.getId() + ", UserId: " + userId); - - if (post == null || userId == null) { - throw new IllegalArgumentException("Post or userId cannot be null"); - } - Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); List userChoiceList=null; @@ -518,6 +512,36 @@ public static PostResponseDTO.PollPostGetListDTO pollPostGetListDTO(Page p .isEnd(postList.isLast()) .build(); } + + public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post post, Long userId){ + Integer likeCount = post.getPostLikeList().size(); + Integer commentCount = post.getCommentList().size(); + Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + return PostResponseDTO.ReviewPostGetResponse.builder() + .nickname(post.getUser().getNickname()) + .title(post.getTitle()) + .content(post.getContent()) + .ReviewPic(post.getFile()) + .uploadDate(post.getCreatedAt()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + + + + } + + public static PostResponseDTO.ReviewPostGetListDTO reviewPostGetListDTO(Page postList,Long userId){ + List reviewPostGetListDTO = postList.stream() + .map(post->reviewPostGetResponse(post,userId)).collect(Collectors.toList()); + return PostResponseDTO.ReviewPostGetListDTO.builder() + .reviewPostList(reviewPostGetListDTO) + .isEnd(postList.isLast()) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 0444cb8..4b78dbc 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -53,6 +53,9 @@ public class Post extends BaseEntity { @Column(nullable = true) private Integer point; + @Column(nullable = true) + private String file; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index f62091e..949dd3b 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -1,7 +1,11 @@ package friend.spring.repository; import friend.spring.domain.Post; +import friend.spring.domain.enums.PostType; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; public interface PostRepository extends JpaRepository { + Page findByPostType(PostType postType, Pageable pageable); } diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index 64814f8..eb5db37 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -1,6 +1,8 @@ package friend.spring.service; import friend.spring.domain.Post; +import friend.spring.web.dto.PostRequestDTO; +import friend.spring.web.dto.PostResponseDTO; import org.springframework.data.domain.Page; import java.util.Optional; @@ -14,4 +16,6 @@ public interface PostQueryService { Optional findPost(Long postId); Page getPostList(Integer page,Integer size); + + Page getReviewList(Integer page, Integer size, Integer arrange); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index ad51d87..b7f665a 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -5,11 +5,14 @@ import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; import friend.spring.repository.*; +import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -84,7 +87,19 @@ public Optional findPost(Long postId) { @Override @Transactional public Page getPostList(Integer page,Integer size){ - return postRepository.findAll(PageRequest.of(page,size, Sort.by(Sort.Direction.ASC,"createdAt"))); + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "createdAt")); + return postRepository.findByPostType(PostType.VOTE, pageable); + } + + @Override + @Transactional + public Page getReviewList(Integer page, Integer size, Integer arrange){ + if(arrange==1){ + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "createdAt")); + return postRepository.findByPostType(PostType.REVIEW, pageable); + } + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "view")); + return postRepository.findByPostType(PostType.REVIEW, pageable); } } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index d8ec4db..eabb3ef 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -62,18 +62,33 @@ public ApiResponse getPostDetail(@PathVariab return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage,userId,parentPost)); } - @GetMapping("/{user-id}") - @Operation(summary = "글 전체 보기 API", description = "글 전체 보기합니다") + @GetMapping("/poll-post/{user-id}") + @Operation(summary = "고민글 전체 보기 API", description = "글 전체 보기합니다") @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)") }) - public ApiResponse getPostDetail( - @RequestParam(name = "page", defaultValue = "0") Integer page, - @RequestParam(name = "size",defaultValue = "15") Integer size, - @RequestParam(name = "user-id") Long userId){ + public ApiResponse getPostDetail(@RequestParam(name = "page", defaultValue = "0") Integer page, + @RequestParam(name = "size",defaultValue = "15") Integer size, + @RequestParam(name = "user-id") Long userId){ Page postPage=postQueryService.getPostList(page,size); return ApiResponse.onSuccess(PostConverter.pollPostGetListDTO(postPage,userId)); } + + @GetMapping("/review-post/{user-id}") + @Operation(summary = "후기글 전체 보기 API", description = "글 전체 보기합니다") + @Parameters({ + @Parameter(name = "arrange", description = "query string(RequestParam) - 정렬 기준 변수입니다. (0: 조회순,1: 최신순) 디폴트값 0"), + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작) 디폴트값 0"), + @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정) 디폴트값 15") + }) + public ApiResponse getReviewDetail(@RequestParam(name="arrange", defaultValue = "0") Integer arrange, + @RequestParam(name = "page", defaultValue = "0") Integer page, + @RequestParam(name = "size",defaultValue = "15") Integer size, + @RequestParam(name = "user-id") Long userId){ + Page postPage=postQueryService.getReviewList(page,size,arrange); + return ApiResponse.onSuccess(PostConverter.reviewPostGetListDTO(postPage,userId)); + + } } diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index 8a05a1e..6845728 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -27,7 +27,11 @@ public static class AddPostDTO{ @NotBlank Timestamp deadline; Integer point; + String file; + } + @Getter + public static class ReviewPostGetDTO{ + Integer arrange; //조회순 :0, 최신순:1 } - } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 02033a8..e1ce55e 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -29,6 +29,7 @@ public static class PostDetailResponse { LocalDateTime createdAt; String title; String content; + String file; String pollTitle; // 투표글에서만 사용, 후기글에서는 null List pollOption; // 투표글에서만 사용, 후기글에서는 null Integer gauge; // 게이지 투표글에서만 사용, 후기글에서는 null @@ -70,6 +71,14 @@ public static class PollPostGetResponse{ Boolean isComment; } + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class ReviewPostGetListDTO{ + List reviewPostList; + private Boolean isEnd; + } @Builder @Data @NoArgsConstructor @@ -78,9 +87,8 @@ public static class ReviewPostGetResponse{ String nickname; String title; String content; - Timestamp uploadDate; - String pollOption; - Integer gauge; + LocalDateTime uploadDate; + String ReviewPic; Integer like; Integer comment; Boolean isLike; From 0815a211669636df68b8725658bcd6a3b38f16e5 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 5 Feb 2024 21:02:40 +0900 Subject: [PATCH 116/255] =?UTF-8?q?#70=20Feat:=20=ED=9B=84=EA=B8=B0=20?= =?UTF-8?q?=EA=B8=80=20=EC=9E=91=EC=84=B1=EC=8B=9C=20=EB=B6=80=EB=AA=A8?= =?UTF-8?q?=EA=B8=80=20=ED=9B=84=EB=B3=B4=20=EB=B6=88=EB=9F=AC=EC=98=A4?= =?UTF-8?q?=EA=B8=B0=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 21 ++++++++++++++++++ .../spring/repository/PostRepository.java | 3 +++ .../spring/service/PostQueryService.java | 2 ++ .../spring/service/PostQueryServiceImpl.java | 8 +++++++ .../web/controller/PostRestController.java | 15 ++++++++++++- .../friend/spring/web/dto/ParentPostDTO.java | 22 +++++++++++++++++++ 6 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 9d57814..78b5ab5 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -542,6 +542,27 @@ public static PostResponseDTO.ReviewPostGetListDTO reviewPostGetListDTO(Page postList,Long userId){ + List parentPostGetListDTO = postList.stream() + .map(post->candidatePostDTO(post)).collect(Collectors.toList()); + return ParentPostDTO.ParentPostGetListDTO.builder() + .candidatePostDTOList(parentPostGetListDTO) + .isEnd(postList.isLast()) + .build(); + } } diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index 949dd3b..003a338 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -6,6 +6,9 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface PostRepository extends JpaRepository { Page findByPostType(PostType postType, Pageable pageable); + Page findByUserIdAndPostType(Long userId, PostType postType, Pageable pageable); } diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index eb5db37..56bb7a4 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -18,4 +18,6 @@ public interface PostQueryService { Page getPostList(Integer page,Integer size); Page getReviewList(Integer page, Integer size, Integer arrange); + + Page getParentPostList(Integer page,Integer size,Long userId); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index b7f665a..7a52550 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -102,4 +102,12 @@ public Page getReviewList(Integer page, Integer size, Integer arrange){ return postRepository.findByPostType(PostType.REVIEW, pageable); } + @Override + @Transactional + public Page getParentPostList(Integer page,Integer size,Long userId){ + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "createdAt")); +// List userPost = postRepository.findByUserId(userId); + return postRepository.findByUserIdAndPostType(userId, PostType.VOTE, pageable); + } + } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index eabb3ef..3781929 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -5,6 +5,7 @@ import friend.spring.repository.PostRepository; import friend.spring.service.PostQueryService; import friend.spring.service.PostService; +import friend.spring.web.dto.ParentPostDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import io.swagger.v3.oas.annotations.Operation; @@ -50,6 +51,19 @@ public ApiResponse join(@RequestBody @Valid Po return ApiResponse.onSuccess(PostConverter.toAddPostResultDTO(post)); } + @GetMapping("/{user-id}/voteList") + @Operation(summary = "후기글 작성시 내투표 보기 API", description = "후기글 작성시 내투표 보기합니다.") + @Parameters({ + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), + @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)") + }) + public ApiResponse getParentPosts(@RequestParam(name = "page", defaultValue = "0") Integer page, + @RequestParam(name = "size",defaultValue = "15") Integer size, + @RequestParam(name = "user-id") Long userId){ + Page postPage=postQueryService.getParentPostList(page,size,userId); + return ApiResponse.onSuccess(PostConverter.parentPostGetListDTO(postPage,userId)); + + } @GetMapping("/{post-id}/{user-id}") @Operation(summary = "글 상세 보기 API", description = "글 상세 보기합니다.") public ApiResponse getPostDetail(@PathVariable(name="post-id")Long PostId, @@ -89,6 +103,5 @@ public ApiResponse getReviewDetail(@Reques @RequestParam(name = "user-id") Long userId){ Page postPage=postQueryService.getReviewList(page,size,arrange); return ApiResponse.onSuccess(PostConverter.reviewPostGetListDTO(postPage,userId)); - } } diff --git a/src/main/java/friend/spring/web/dto/ParentPostDTO.java b/src/main/java/friend/spring/web/dto/ParentPostDTO.java index c34bc3b..d0e8467 100644 --- a/src/main/java/friend/spring/web/dto/ParentPostDTO.java +++ b/src/main/java/friend/spring/web/dto/ParentPostDTO.java @@ -2,6 +2,7 @@ import lombok.*; +import java.time.LocalDateTime; import java.util.List; @Getter @@ -18,6 +19,27 @@ public class ParentPostDTO { Integer gauge; Integer like; Integer comment; + + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class CandidatePostDTO { + String title; + String content; + Integer like; + Integer comment; + LocalDateTime createdAt; + } + + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class ParentPostGetListDTO{ + List candidatePostDTOList; + private Boolean isEnd; + } } From d7c4b5d1a830d9ca0c5d24f6bc17ded4a5ffb2dc Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 5 Feb 2024 22:36:33 +0900 Subject: [PATCH 117/255] =?UTF-8?q?#70=20Feat:=20=EA=B8=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95(=EC=A0=9C=EB=AA=A9,=20=EB=82=B4=EC=9A=A9)API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/converter/PostConverter.java | 1 + src/main/java/friend/spring/domain/Post.java | 8 ++++++++ .../java/friend/spring/service/PostService.java | 2 ++ .../friend/spring/service/PostServiceImpl.java | 17 +++++++++++++++++ .../web/controller/PostRestController.java | 14 ++++++++++++++ .../friend/spring/web/dto/PostRequestDTO.java | 14 ++++++++++++++ 6 files changed, 56 insertions(+) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 78b5ab5..c73b97d 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -203,6 +203,7 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { .build(); } + public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, Boolean engage,Long userId, Post parentPost){ Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 4b78dbc..817ade2 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -139,4 +139,12 @@ public void setCardPoll(Card_poll cardPoll) { cardPoll.setPost(this); } } + + public void setTitle(String title){ + this.title=title; + } + + public void setContent(String content){ + this.content=content; + } } diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index 623804a..65d1517 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -10,5 +10,7 @@ public interface PostService { Post joinPost(PostRequestDTO.AddPostDTO request, Long userId); Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user); + + void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 82a00dc..aad7fc5 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -1,5 +1,6 @@ package friend.spring.service; +import friend.spring.apiPayload.GeneralException; import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.apiPayload.handler.UserHandler; import friend.spring.converter.PostConverter; @@ -12,6 +13,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Objects; + import static friend.spring.domain.enums.PostType.*; import static friend.spring.domain.enums.PostVoteType.*; @@ -168,4 +171,18 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { return postRepository.save(newPost); } + + @Override + @Transactional + public void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId){ + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + if(!user.getId().equals(post.getUser().getId())){ + throw new RuntimeException("수정 권환이 없습니다 글이 없습니다"); + } + post.setTitle(request.getTitle()); + post.setContent(request.getContent()); + + } + } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 3781929..6ab6aa5 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -104,4 +104,18 @@ public ApiResponse getReviewDetail(@Reques Page postPage=postQueryService.getReviewList(page,size,arrange); return ApiResponse.onSuccess(PostConverter.reviewPostGetListDTO(postPage,userId)); } + + @PatchMapping("{post-id}/post/{user-id}/edit") + @Operation(summary = "글 수정 API", description = "댓글 수정하는 API입니다. ex) /posts/1/comment/1/edit") + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + }) + public ApiResponse editPost(@PathVariable("post-id") Long postId, + @RequestBody PostRequestDTO.PostEditReq request, + @RequestHeader("userId") Long userId + ) { + postService.editPost(postId, request, userId); + return ApiResponse.onSuccess(null); + } } diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index 6845728..efd4817 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -2,7 +2,10 @@ import friend.spring.domain.Post; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import org.apache.tomcat.jni.Poll; import javax.validation.constraints.NotBlank; @@ -34,4 +37,15 @@ public static class ReviewPostGetDTO{ Integer arrange; //조회순 :0, 최신순:1 } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class PostEditReq { + @NotBlank + String title; + @NotBlank + String content; + } + } From 56758c7b7ca7095948dc147bf73db4794c0ffe01 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 5 Feb 2024 22:54:36 +0900 Subject: [PATCH 118/255] =?UTF-8?q?#70=20Feat:=20=EA=B8=80=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Post.java | 4 ++++ .../java/friend/spring/service/PostService.java | 3 +++ .../friend/spring/service/PostServiceImpl.java | 12 ++++++++++++ .../web/controller/PostRestController.java | 16 +++++++++++++++- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 817ade2..9db2158 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -147,4 +147,8 @@ public void setTitle(String title){ public void setContent(String content){ this.content=content; } + + public void setStateDel(){ + this.state=PostState.DELETED; + } } diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index 65d1517..95286b9 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -7,10 +7,13 @@ public interface PostService { void checkPost(Boolean flag); + Post joinPost(PostRequestDTO.AddPostDTO request, Long userId); Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user); void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId); + + void deletePost(Long postId, Long userId); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index aad7fc5..0858da6 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -185,4 +185,16 @@ public void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId } + @Override + @Transactional + public void deletePost(Long postId, Long userId) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + if(!user.getId().equals(post.getUser().getId())){ + throw new RuntimeException("삭제 권환이 없습니다 글이 없습니다"); + } + post.setStateDel(); + } + + } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 6ab6aa5..c78548b 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -105,7 +105,7 @@ public ApiResponse getReviewDetail(@Reques return ApiResponse.onSuccess(PostConverter.reviewPostGetListDTO(postPage,userId)); } - @PatchMapping("{post-id}/post/{user-id}/edit") + @PatchMapping("/{post-id}/post/{user-id}/edit") @Operation(summary = "글 수정 API", description = "댓글 수정하는 API입니다. ex) /posts/1/comment/1/edit") @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @@ -118,4 +118,18 @@ public ApiResponse editPost(@PathVariable("post-id") Long postId, postService.editPost(postId, request, userId); return ApiResponse.onSuccess(null); } + + @PatchMapping("/{post-id}/post/{user-id}/del") + @Operation(summary = "댓글 삭제 API", description = "댓글 삭제하는 API입니다. ex) /posts/1/comment/1/del") + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)") + }) + public ApiResponse deleteComment( + @PathVariable("post-id") Long postId, + @RequestHeader("userId") Long userId + ) { + postService.deletePost(postId, userId); + return ApiResponse.onSuccess(null); + } } From 0adb1db55fad29f5f44f6fa158c7c6bc48f1d8ca Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 5 Feb 2024 23:12:56 +0900 Subject: [PATCH 119/255] =?UTF-8?q?#70=20Feat:=20=EA=B8=80=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=EC=8B=9C=20STATE=EC=83=81=ED=83=9C=EB=A7=8C=20?= =?UTF-8?q?=EB=82=98=EC=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/PostConverter.java | 1 + .../java/friend/spring/repository/PostRepository.java | 5 +++-- .../java/friend/spring/service/PostQueryServiceImpl.java | 9 +++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index c73b97d..a54df87 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -374,6 +374,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .build(); } + //전체 보기 public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Long userId){ //로컬 db test if(post.getPostType()==VOTE&&post.getVoteType()==null){ diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index 003a338..e6e5e9b 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -1,6 +1,7 @@ package friend.spring.repository; import friend.spring.domain.Post; +import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -9,6 +10,6 @@ import java.util.List; public interface PostRepository extends JpaRepository { - Page findByPostType(PostType postType, Pageable pageable); - Page findByUserIdAndPostType(Long userId, PostType postType, Pageable pageable); + Page findByPostTypeAndState(PostType postType, PostState state, Pageable pageable); + Page findByUserIdAndPostTypeAndState(Long userId, PostType postType, PostState state, Pageable pageable); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 7a52550..9d6fb96 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -2,6 +2,7 @@ import friend.spring.converter.PostConverter; import friend.spring.domain.*; +import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; import friend.spring.repository.*; @@ -88,7 +89,7 @@ public Optional findPost(Long postId) { @Transactional public Page getPostList(Integer page,Integer size){ Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "createdAt")); - return postRepository.findByPostType(PostType.VOTE, pageable); + return postRepository.findByPostTypeAndState(PostType.VOTE, PostState.POSTING, pageable); } @Override @@ -96,10 +97,10 @@ public Page getPostList(Integer page,Integer size){ public Page getReviewList(Integer page, Integer size, Integer arrange){ if(arrange==1){ Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "createdAt")); - return postRepository.findByPostType(PostType.REVIEW, pageable); + return postRepository.findByPostTypeAndState(PostType.REVIEW, PostState.POSTING, pageable); } Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "view")); - return postRepository.findByPostType(PostType.REVIEW, pageable); + return postRepository.findByPostTypeAndState(PostType.REVIEW, PostState.POSTING, pageable); } @Override @@ -107,7 +108,7 @@ public Page getReviewList(Integer page, Integer size, Integer arrange){ public Page getParentPostList(Integer page,Integer size,Long userId){ Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "createdAt")); // List userPost = postRepository.findByUserId(userId); - return postRepository.findByUserIdAndPostType(userId, PostType.VOTE, pageable); + return postRepository.findByUserIdAndPostTypeAndState(userId, PostType.VOTE, PostState.POSTING, pageable); } } From 25b00078db31c6d936fd7a0a37d4425a41ea40b7 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 5 Feb 2024 23:32:16 +0900 Subject: [PATCH 120/255] =?UTF-8?q?#70=20Feat:=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94=20=EB=8C=93=EA=B8=80=20=ED=81=B4=EB=A6=AD=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=20=ED=99=95=EC=9D=B8=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/converter/PostConverter.java | 11 +++++++++++ .../java/friend/spring/web/dto/PostResponseDTO.java | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index a54df87..12028de 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -204,6 +204,7 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { } + //글 상세 보기 public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, Boolean engage,Long userId, Post parentPost){ Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); @@ -211,6 +212,8 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B List percent=null; List voteResult=null; Integer value=null; + Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); if(post.getPostType()==REVIEW){ @@ -224,6 +227,8 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .view(post.getView()) .like(likeCount) .comment(commentCount) + .isLike(isLike) + .isComment(isComment) .build(); } if(post.getVoteType()==PostVoteType.GAUGE){ @@ -242,6 +247,8 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .view(post.getView()) .like(likeCount) .comment(commentCount) + .isLike(isLike) + .isComment(isComment) .build(); } if(post.getVoteType()==PostVoteType.GENERAL){ @@ -307,6 +314,8 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .view(post.getView()) .like(likeCount) .comment(commentCount) + .isLike(isLike) + .isComment(isComment) .build(); } List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() @@ -371,6 +380,8 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .view(post.getView()) .like(likeCount) .comment(commentCount) + .isLike(isLike) + .isComment(isComment) .build(); } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index e1ce55e..a35cb1f 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -42,6 +42,8 @@ public static class PostDetailResponse { Integer view; Integer like; Integer comment; + Boolean isLike; + Boolean isComment; } From 2ea08c596b3beac9bf9eb6775c6a70bebe1d33f2 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 6 Feb 2024 00:45:10 +0900 Subject: [PATCH 121/255] =?UTF-8?q?#67=20Chore:=20Elasticache=20Redis?= =?UTF-8?q?=EB=A1=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index cfae2a6..66bf71e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,9 +1,9 @@ spring: redis: - host: localhost - port: 6379 + host: ${REDIS_HOSTNAME} + port: ${REDIS_PORT} jwt: - secret: c4lsdmVybmluZS10ZWNoLXNwcmluZy1ib290LWp3dC10dXRvcmlhbC1zZWNyZXQtc2lsdmVybmluZS10ZWNoLXNwcmluZy1ib290LWp3dC10dXRvcmlhbC1zZWNyZXQK + secret: ${JWT_SECRET} datasource: url: ${aws.db.url} username: ${aws.db.username} From 29021705e38fcbae1ee5bc0f44084b0c7d862513 Mon Sep 17 00:00:00 2001 From: hjh Date: Tue, 6 Feb 2024 00:50:30 +0900 Subject: [PATCH 122/255] =?UTF-8?q?#72=20Feat:=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=ED=85=8C=EC=9D=B4=EB=B8=94=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=84=A4=EC=A0=95.(=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EA=B8=80=20=EC=A0=95=EB=A0=AC,=20=EA=B8=80=EC=93=B0=EA=B8=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 28 ------------------- src/main/java/friend/spring/domain/Post.java | 10 +++++++ .../spring/repository/PostRepository.java | 2 ++ .../spring/service/PostQueryService.java | 2 +- .../spring/service/PostQueryServiceImpl.java | 15 ++++++---- .../spring/service/PostServiceImpl.java | 7 ++++- .../web/controller/PostRestController.java | 14 ++++++---- .../friend/spring/web/dto/PostRequestDTO.java | 3 +- 8 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 12028de..1093151 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -1,11 +1,9 @@ package friend.spring.converter; import friend.spring.domain.*; -import friend.spring.domain.enums.PostCategory; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; import friend.spring.service.PostQueryService; -import friend.spring.service.PostQueryServiceImpl; import friend.spring.web.dto.*; import org.springframework.data.domain.Page; @@ -137,7 +135,6 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ public static Post toPost(PostRequestDTO.AddPostDTO request) { PostType postType=null; PostVoteType postVoteType=null; - PostCategory category=null; switch (request.getPostType()){ case 1: @@ -166,36 +163,11 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { } } - switch (request.getCategory()){ - case 1: - category=PostCategory.EDUCATION; - break; - case 2: - category=PostCategory.ENTERTAINMENT; - break; - case 3: - category=PostCategory.LIFESTYLE; - break; - case 4: - category=PostCategory.ECONOMY; - break; - case 5: - category=PostCategory.SHOPPING; - break; - case 6: - category=PostCategory.OTHERS; - break; - default: - break; - } - - return Post.builder() .title(request.getTitle()) .content(request.getContent()) .file(request.getFile()) .postType(postType) - .category(category) .voteType(postVoteType) .point(request.getPoint()) .view(0) diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 9db2158..ba1eb6f 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -60,6 +60,9 @@ public class Post extends BaseEntity { @JoinColumn(name = "user_id") private User user; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "category_id") + private Category postCategory; // 부모 글 정의 // 고민후기 원글 아이디 @ManyToOne(fetch = FetchType.LAZY) @@ -114,6 +117,13 @@ public void setParentPost(Post parent){ parent.getReviewPostList().add(this); } + public void setCategory(Category category){ + if(this.postCategory != null) + category.getPostList().remove(this); + this.postCategory=category; + category.getPostList().add(this); + } + public void setView(Integer view) { this.view = view; } diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index e6e5e9b..79130b9 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -1,5 +1,6 @@ package friend.spring.repository; +import friend.spring.domain.Category; import friend.spring.domain.Post; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; @@ -11,5 +12,6 @@ public interface PostRepository extends JpaRepository { Page findByPostTypeAndState(PostType postType, PostState state, Pageable pageable); + Page findByPostTypeAndStateAndPostCategory(PostType postType, PostState state,Category postCategory,Pageable pageable); Page findByUserIdAndPostTypeAndState(Long userId, PostType postType, PostState state, Pageable pageable); } diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index 56bb7a4..aa64767 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -15,7 +15,7 @@ public interface PostQueryService { Optional findPost(Long postId); - Page getPostList(Integer page,Integer size); + Page getPostList(Integer page,Integer size, String category); Page getReviewList(Integer page, Integer size, Integer arrange); diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 9d6fb96..b2bc98e 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -29,6 +29,7 @@ public class PostQueryServiceImpl implements PostQueryService{ private final General_VoteRepository generalVoteRepository; private final Gauge_VoteRepository gaugeVoteRepository; private final Card_VoteRepository cardVoteRepository; + private final CategoryRepository categoryRepository; @Override @Transactional public Optional getPostDetail(Long postId){ @@ -87,16 +88,20 @@ public Optional findPost(Long postId) { @Override @Transactional - public Page getPostList(Integer page,Integer size){ - Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "createdAt")); - return postRepository.findByPostTypeAndState(PostType.VOTE, PostState.POSTING, pageable); + public Page getPostList(Integer page,Integer size,String category){ + if(category=="ALL"){ + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); + return postRepository.findByPostTypeAndState(PostType.VOTE, PostState.POSTING, pageable);} + Category category1 = categoryRepository.findByName(category); + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); + return postRepository.findByPostTypeAndStateAndPostCategory(PostType.VOTE, PostState.POSTING,category1, pageable); } @Override @Transactional public Page getReviewList(Integer page, Integer size, Integer arrange){ if(arrange==1){ - Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "createdAt")); + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); return postRepository.findByPostTypeAndState(PostType.REVIEW, PostState.POSTING, pageable); } Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "view")); @@ -106,7 +111,7 @@ public Page getReviewList(Integer page, Integer size, Integer arrange){ @Override @Transactional public Page getParentPostList(Integer page,Integer size,Long userId){ - Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "createdAt")); + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); // List userPost = postRepository.findByUserId(userId); return postRepository.findByUserIdAndPostTypeAndState(userId, PostType.VOTE, PostState.POSTING, pageable); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 0858da6..9343a58 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -30,6 +30,7 @@ public class PostServiceImpl implements PostService{ private final Gauge_PollRepository gaugePollRepository; private final Card_PollRepository cardPollRepository; private final PointRepository pointRepository; + private final CategoryRepository categoryRepository; @Override public void checkPost(Boolean flag) { if (!flag) { @@ -55,7 +56,11 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { .orElseThrow(()->new RuntimeException("\""+userId+"\"해당 유저가 없습니다")); newPost.setUser(user); -//일반 투표 api + //일반 투표 api + if(newPost.getPostType()==VOTE){ + newPost.setCategory(categoryRepository.findByName(request.getCategory())); + + } if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL&&request.getPollOption()!=null){ //포인트 차감 관련 코드 if(request.getPoint()!=null) { diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index c78548b..6e0147c 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -33,8 +33,7 @@ public class PostRestController { @Parameters({ @Parameter(name="title", description=" 글 제목"), @Parameter(name="content", description=" 글 내용"), - @Parameter(name="category", description=" 카테고리
1 : EDUCATION
2 : ENTERTAINMENT
3 : LIFESTYLE
4 : ECONOMY
5 : SHOPPING" + - "
6 : OTHERS" ), + @Parameter(name="category", description="카테고리. 대문자(ex EDUCATION)" ), @Parameter(name="postType", description=" 글 종류
1 : NOT_VOTE
2 : VOTE
3 : REVIEW"), @Parameter(name="postVoteType", description=" 투표 종류
1 : GENERAL
2 : GAUGE
3 : CARD
해당 사항 없을시 null"), @Parameter(name="pollTitle", description=" 투표 제목"), @@ -76,16 +75,19 @@ public ApiResponse getPostDetail(@PathVariab return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage,userId,parentPost)); } - @GetMapping("/poll-post/{user-id}") + @GetMapping("/poll-post/{user-id}/{category}") @Operation(summary = "고민글 전체 보기 API", description = "글 전체 보기합니다") @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), - @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)") + @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)"), + @Parameter(name = "user-id", description = "query string(RequestParam) - user id"), + @Parameter(name = "category", description = "query string(RequestParam) - category(대문자). 모두 보기는 ALL") }) public ApiResponse getPostDetail(@RequestParam(name = "page", defaultValue = "0") Integer page, @RequestParam(name = "size",defaultValue = "15") Integer size, - @RequestParam(name = "user-id") Long userId){ - Page postPage=postQueryService.getPostList(page,size); + @RequestParam(name = "user-id") Long userId, + @RequestParam(name = "category") String category){ + Page postPage=postQueryService.getPostList(page,size,category); return ApiResponse.onSuccess(PostConverter.pollPostGetListDTO(postPage,userId)); } diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index efd4817..42dbd66 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -1,6 +1,7 @@ package friend.spring.web.dto; +import friend.spring.domain.Category; import friend.spring.domain.Post; import lombok.AllArgsConstructor; import lombok.Builder; @@ -19,7 +20,7 @@ public static class AddPostDTO{ String title; @NotBlank String content; - Integer category; //미정 + String category; @NotBlank Integer postType; // 1: vote, 2: review Integer postVoteType;// 1: general, 2: gauge From 0ab0ba274981635accbcc25da365c4eb33557ced Mon Sep 17 00:00:00 2001 From: hjh Date: Tue, 6 Feb 2024 01:02:42 +0900 Subject: [PATCH 123/255] =?UTF-8?q?#72=20Feat:=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=ED=85=8C=EC=9D=B4=EB=B8=94=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=84=A4=EC=A0=95.(=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EA=B8=80=20=EC=A0=95=EB=A0=AC,=20=EA=B8=80=EC=93=B0=EA=B8=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/VoteConverter.java | 1 - .../java/friend/spring/domain/Category.java | 27 +++++++++++++++++++ src/main/java/friend/spring/domain/Post.java | 3 --- .../spring/domain/enums/PostCategory.java | 6 ----- .../spring/repository/CategoryRepository.java | 11 ++++++++ 5 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/main/java/friend/spring/domain/Category.java delete mode 100644 src/main/java/friend/spring/domain/enums/PostCategory.java create mode 100644 src/main/java/friend/spring/repository/CategoryRepository.java diff --git a/src/main/java/friend/spring/converter/VoteConverter.java b/src/main/java/friend/spring/converter/VoteConverter.java index 3f8e72d..7d2d667 100644 --- a/src/main/java/friend/spring/converter/VoteConverter.java +++ b/src/main/java/friend/spring/converter/VoteConverter.java @@ -4,7 +4,6 @@ import friend.spring.domain.Gauge_vote; import friend.spring.domain.General_vote; import friend.spring.domain.Post; -import friend.spring.domain.enums.PostCategory; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; diff --git a/src/main/java/friend/spring/domain/Category.java b/src/main/java/friend/spring/domain/Category.java new file mode 100644 index 0000000..2d10ae4 --- /dev/null +++ b/src/main/java/friend/spring/domain/Category.java @@ -0,0 +1,27 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import lombok.*; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Category extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String name; + + @Builder.Default + @OneToMany(mappedBy = "postCategory") + private List postList = new ArrayList<>(); +} \ No newline at end of file diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index ba1eb6f..4b7bf2e 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -1,7 +1,6 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; -import friend.spring.domain.enums.PostCategory; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; @@ -38,8 +37,6 @@ public class Post extends BaseEntity { @Column private PostVoteType voteType; - @Enumerated(EnumType.STRING) - private PostCategory category; @Enumerated(EnumType.STRING) @Column diff --git a/src/main/java/friend/spring/domain/enums/PostCategory.java b/src/main/java/friend/spring/domain/enums/PostCategory.java deleted file mode 100644 index 33b20d9..0000000 --- a/src/main/java/friend/spring/domain/enums/PostCategory.java +++ /dev/null @@ -1,6 +0,0 @@ -package friend.spring.domain.enums; - -//미정. 그냥 예시. -public enum PostCategory { - EDUCATION, ENTERTAINMENT, LIFESTYLE, ECONOMY, SHOPPING, OTHERS -} diff --git a/src/main/java/friend/spring/repository/CategoryRepository.java b/src/main/java/friend/spring/repository/CategoryRepository.java new file mode 100644 index 0000000..d5cb5da --- /dev/null +++ b/src/main/java/friend/spring/repository/CategoryRepository.java @@ -0,0 +1,11 @@ +package friend.spring.repository; + +import friend.spring.domain.Card_vote; +import friend.spring.domain.Category; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface CategoryRepository extends JpaRepository { + Category findByName(String category); +} From aed52fc26dc8a21d7227f4b71340b9286deeed6b Mon Sep 17 00:00:00 2001 From: hjh Date: Tue, 6 Feb 2024 01:16:51 +0900 Subject: [PATCH 124/255] =?UTF-8?q?#72=20Feat:=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=ED=85=8C=EC=9D=B4=EB=B8=94=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=84=A4=EC=A0=95.(=EC=99=84=EB=A3=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Category.java | 2 +- src/main/java/friend/spring/domain/Post.java | 6 +++--- src/main/java/friend/spring/repository/PostRepository.java | 2 +- .../java/friend/spring/service/PostQueryServiceImpl.java | 2 +- .../friend/spring/web/controller/PostRestController.java | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/friend/spring/domain/Category.java b/src/main/java/friend/spring/domain/Category.java index 2d10ae4..283ef9b 100644 --- a/src/main/java/friend/spring/domain/Category.java +++ b/src/main/java/friend/spring/domain/Category.java @@ -22,6 +22,6 @@ public class Category extends BaseEntity { private String name; @Builder.Default - @OneToMany(mappedBy = "postCategory") + @OneToMany(mappedBy = "category") private List postList = new ArrayList<>(); } \ No newline at end of file diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 4b7bf2e..3ffe83d 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -59,7 +59,7 @@ public class Post extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "category_id") - private Category postCategory; + private Category category; // 부모 글 정의 // 고민후기 원글 아이디 @ManyToOne(fetch = FetchType.LAZY) @@ -115,9 +115,9 @@ public void setParentPost(Post parent){ } public void setCategory(Category category){ - if(this.postCategory != null) + if(this.category != null) category.getPostList().remove(this); - this.postCategory=category; + this.category =category; category.getPostList().add(this); } diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index 79130b9..fc14ae3 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -12,6 +12,6 @@ public interface PostRepository extends JpaRepository { Page findByPostTypeAndState(PostType postType, PostState state, Pageable pageable); - Page findByPostTypeAndStateAndPostCategory(PostType postType, PostState state,Category postCategory,Pageable pageable); + Page findByPostTypeAndStateAndCategory(PostType postType, PostState state,Category postCategory,Pageable pageable); Page findByUserIdAndPostTypeAndState(Long userId, PostType postType, PostState state, Pageable pageable); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index b2bc98e..87d2042 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -94,7 +94,7 @@ public Page getPostList(Integer page,Integer size,String category){ return postRepository.findByPostTypeAndState(PostType.VOTE, PostState.POSTING, pageable);} Category category1 = categoryRepository.findByName(category); Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); - return postRepository.findByPostTypeAndStateAndPostCategory(PostType.VOTE, PostState.POSTING,category1, pageable); + return postRepository.findByPostTypeAndStateAndCategory(PostType.VOTE, PostState.POSTING,category1, pageable); } @Override diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 6e0147c..e49a323 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -34,7 +34,7 @@ public class PostRestController { @Parameter(name="title", description=" 글 제목"), @Parameter(name="content", description=" 글 내용"), @Parameter(name="category", description="카테고리. 대문자(ex EDUCATION)" ), - @Parameter(name="postType", description=" 글 종류
1 : NOT_VOTE
2 : VOTE
3 : REVIEW"), + @Parameter(name="postType", description=" 글 종류
1 : VOTE
2 : REVIEW"), @Parameter(name="postVoteType", description=" 투표 종류
1 : GENERAL
2 : GAUGE
3 : CARD
해당 사항 없을시 null"), @Parameter(name="pollTitle", description=" 투표 제목"), @Parameter(name="multipleChoice", description=" 복수 선택 여부"), From ad4ad3dd553d40e8a71be6b7bfdfbdcc085749bd Mon Sep 17 00:00:00 2001 From: hjh Date: Tue, 6 Feb 2024 01:18:37 +0900 Subject: [PATCH 125/255] =?UTF-8?q?#72=20Feat:=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=ED=85=8C=EC=9D=B4=EB=B8=94=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=84=A4=EC=A0=95.(=EC=99=84=EB=A3=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/repository/PostRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index fc14ae3..ff1615b 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -12,6 +12,6 @@ public interface PostRepository extends JpaRepository { Page findByPostTypeAndState(PostType postType, PostState state, Pageable pageable); - Page findByPostTypeAndStateAndCategory(PostType postType, PostState state,Category postCategory,Pageable pageable); + Page findByPostTypeAndStateAndCategory(PostType postType, PostState state,Category category,Pageable pageable); Page findByUserIdAndPostTypeAndState(Long userId, PostType postType, PostState state, Pageable pageable); } From dc0f47388fb316e9da0a23e0c10a053b7b7538a4 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 6 Feb 2024 03:29:24 +0900 Subject: [PATCH 126/255] =?UTF-8?q?#67=20Refactor:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=ED=86=A0=ED=81=B0=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=95=B4=EC=84=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 5 -- .../friend/spring/service/CommentService.java | 13 ++--- .../spring/service/CommentServiceImpl.java | 35 ++++++++++---- .../friend/spring/service/PostService.java | 4 +- .../spring/service/PostServiceImpl.java | 8 +++- .../web/controller/CommentRestController.java | 47 +++++++++++-------- .../web/controller/PostRestController.java | 14 +++--- 7 files changed, 75 insertions(+), 51 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index ae98f99..a82dae8 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -13,17 +13,12 @@ import java.util.stream.Collectors; import friend.spring.domain.Post; import friend.spring.domain.User; -import friend.spring.domain.enums.PostCategory; -import friend.spring.domain.enums.PostState; -import friend.spring.domain.enums.PostType; -import friend.spring.domain.enums.PostVoteType; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; import friend.spring.web.dto.CandidateResponseDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; -import java.time.LocalDateTime; import java.util.List; import static friend.spring.domain.enums.PostType.*; diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index edac1ce..808de43 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -7,6 +7,7 @@ import friend.spring.web.dto.CommentResponseDTO; import org.springframework.data.domain.Page; +import javax.servlet.http.HttpServletRequest; import java.util.List; public interface CommentService { @@ -16,19 +17,19 @@ public interface CommentService { void checkSelectCommentAnotherUser(Boolean flag); void checkCommentWriterUser(Boolean flag); - public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId); + public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq requestBody, HttpServletRequest request); - Comment_like likeComment(Long postId, Long commentId, Long userId); + Comment_like likeComment(Long postId, Long commentId, HttpServletRequest request); Page getComments(Long postId, Integer page, Integer size); - void dislikeComment(Long postId, Long commentId, Long userId); + void dislikeComment(Long postId, Long commentId, HttpServletRequest request); - Comment_choice selectComment(Long postId, Long commentId, Long userId); + Comment_choice selectComment(Long postId, Long commentId, HttpServletRequest request); - void editComment(Long postId, Long commentId, CommentRequestDTO.commentEditReq request, Long userId); + void editComment(Long postId, Long commentId, CommentRequestDTO.commentEditReq requestBody, HttpServletRequest request); Page getMyCommentList(Long userId, Integer page); - void deleteComment(Long postId, Long commentId, Long userId); + void deleteComment(Long postId, Long commentId, HttpServletRequest request); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index b83e485..cd03927 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -10,6 +10,7 @@ import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.repository.*; +import friend.spring.security.JwtTokenProvider; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; import lombok.RequiredArgsConstructor; @@ -20,6 +21,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.servlet.http.HttpServletRequest; import java.util.*; import java.util.stream.Collectors; @@ -35,6 +37,7 @@ public class CommentServiceImpl implements CommentService { private final CommentChoiceRepository commentChoiceRepository; private final UserService userService; private final PostService postService; + private final JwtTokenProvider jwtTokenProvider; @Override public void checkComment(Boolean flag) { @@ -73,7 +76,9 @@ public void checkCommentWriterUser(Boolean flag) { @Override @Transactional - public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq request, Long userId) { + public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq requestBody, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { postService.checkPost(false); @@ -89,8 +94,8 @@ public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq req User user = optionalUser.get(); // 대댓글인 경우 - if (request.getParentId() != null) { - Optional optionalParentComment = commentRepository.findById(request.getParentId()); + if (requestBody.getParentId() != null) { + Optional optionalParentComment = commentRepository.findById(requestBody.getParentId()); if (optionalParentComment.isEmpty()) { this.checkComment(false); } @@ -98,13 +103,15 @@ public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq req parentComment = optionalParentComment.get(); } - Comment comment = CommentConverter.toComment(request, post, user, parentComment); + Comment comment = CommentConverter.toComment(requestBody, post, user, parentComment); return commentRepository.save(comment); } @Override - public Comment_like likeComment(Long postId, Long commentId, Long userId) { + public Comment_like likeComment(Long postId, Long commentId, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { postService.checkPost(false); @@ -150,7 +157,9 @@ public Page getComments(Long postId, Integer p } @Override - public void dislikeComment(Long postId, Long commentId, Long userId) { + public void dislikeComment(Long postId, Long commentId, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { postService.checkPost(false); @@ -176,7 +185,9 @@ public void dislikeComment(Long postId, Long commentId, Long userId) { } @Override - public Comment_choice selectComment(Long postId, Long commentId, Long userId) { + public Comment_choice selectComment(Long postId, Long commentId, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { postService.checkPost(false); @@ -219,7 +230,9 @@ public Comment_choice selectComment(Long postId, Long commentId, Long userId) { @Override @Transactional - public void editComment(Long postId, Long commentId, CommentRequestDTO.commentEditReq request, Long userId) { + public void editComment(Long postId, Long commentId, CommentRequestDTO.commentEditReq requestBody, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); Comment comment = commentRepository.findById(commentId).orElseThrow(() -> new GeneralException(ErrorStatus.COMMENT_NOT_FOUND)); @@ -228,7 +241,7 @@ public void editComment(Long postId, Long commentId, CommentRequestDTO.commentEd // 작성자가 아닌 경우 -> 에러 반환 this.checkCommentWriterUser(false); } - comment.update(request.getContent()); + comment.update(requestBody.getContent()); } //한 유저의 모든 댓글 @@ -245,7 +258,9 @@ public Page getMyCommentList(Long userId, Integer page) { @Override @Transactional - public void deleteComment(Long postId, Long commentId, Long userId) { + public void deleteComment(Long postId, Long commentId, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); Comment comment = commentRepository.findById(commentId).orElseThrow(() -> new GeneralException(ErrorStatus.COMMENT_NOT_FOUND)); diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index b2759c6..780a136 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -31,9 +31,9 @@ public interface PostService { Page getMyPostList(Long userId, Integer page); - Post_like likePost(Long postId, Long userId); + Post_like likePost(Long postId, HttpServletRequest request); - void dislikePost(Long postId, Long userId); + void dislikePost(Long postId, HttpServletRequest request); void checkPostScrap(Boolean flag); diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index f85cf27..4f47672 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -257,7 +257,9 @@ public Page getMyPostList(Long userId, Integer page) { } @Override - public Post_like likePost(Long postId, Long userId) { + public Post_like likePost(Long postId, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { this.checkPost(false); @@ -276,7 +278,9 @@ public Post_like likePost(Long postId, Long userId) { } @Override - public void dislikePost(Long postId, Long userId) { + public void dislikePost(Long postId, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { this.checkPost(false); diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 9d086ea..418dc26 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -19,6 +19,7 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; import java.util.List; @RestController @@ -39,14 +40,15 @@ public class CommentRestController { }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse createComment( @PathVariable("post-id") Long postId, - @RequestBody CommentRequestDTO.commentCreateReq request, - @RequestHeader("userId") Long userId + @RequestBody CommentRequestDTO.commentCreateReq requestBody, + @RequestHeader(name = "atk") String atk, + HttpServletRequest request ) { - Comment comment = commentService.createComment(postId, request, userId); + Comment comment = commentService.createComment(postId, requestBody, request); return ApiResponse.onSuccess(CommentConverter.toCommentCreateRes(comment)); } @@ -62,14 +64,15 @@ public ApiResponse createComment( @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @Parameter(name = "comment-id", description = "path variable - 댓글 아이디"), - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse likeComment( @PathVariable("post-id") Long postId, @PathVariable("comment-id") Long commentId, - @RequestHeader("userId") Long userId + @RequestHeader(name = "atk") String atk, + HttpServletRequest request ) { - Comment_like comment_like = commentService.likeComment(postId, commentId, userId); + Comment_like comment_like = commentService.likeComment(postId, commentId, request); return ApiResponse.onSuccess(CommentConverter.toCommentLikeRes(comment_like)); } @@ -86,14 +89,15 @@ public ApiResponse likeComment( @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @Parameter(name = "comment-id", description = "path variable - 댓글 아이디"), - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse dislikeComment( @PathVariable("post-id") Long postId, @PathVariable("comment-id") Long commentId, - @RequestHeader("userId") Long userId + @RequestHeader(name = "atk") String atk, + HttpServletRequest request ) { - commentService.dislikeComment(postId, commentId, userId); + commentService.dislikeComment(postId, commentId, request); return ApiResponse.onSuccess(null); } @@ -133,14 +137,15 @@ public ApiResponse> getComments( @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @Parameter(name = "comment-id", description = "path variable - 댓글 아이디"), - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse selectComment( @PathVariable("post-id") Long postId, @PathVariable("comment-id") Long commentId, - @RequestHeader("userId") Long userId + @RequestHeader(name = "atk") String atk, + HttpServletRequest request ) { - Comment_choice comment_choice = commentService.selectComment(postId, commentId, userId); + Comment_choice comment_choice = commentService.selectComment(postId, commentId, request); return ApiResponse.onSuccess(CommentConverter.toCommentSelectRes(comment_choice)); } @@ -157,15 +162,16 @@ public ApiResponse selectComment( @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @Parameter(name = "comment-id", description = "path variable - 댓글 아이디"), - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse editComment( @PathVariable("post-id") Long postId, @PathVariable("comment-id") Long commentId, - @RequestBody CommentRequestDTO.commentEditReq request, - @RequestHeader("userId") Long userId + @RequestBody CommentRequestDTO.commentEditReq requestBody, + @RequestHeader(name = "atk") String atk, + HttpServletRequest request ) { - commentService.editComment(postId, commentId, request, userId); + commentService.editComment(postId, commentId, requestBody, request); return ApiResponse.onSuccess(null); } @@ -182,14 +188,15 @@ public ApiResponse editComment( @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @Parameter(name = "comment-id", description = "path variable - 댓글 아이디"), - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse deleteComment( @PathVariable("post-id") Long postId, @PathVariable("comment-id") Long commentId, - @RequestHeader("userId") Long userId + @RequestHeader(name = "atk") String atk, + HttpServletRequest request ) { - commentService.deleteComment(postId, commentId, userId); + commentService.deleteComment(postId, commentId, request); return ApiResponse.onSuccess(null); } } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index e4fd6cd..6245403 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -154,13 +154,14 @@ public ApiResponse deleteComment( }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse likePost( @PathVariable("post-id") Long postId, - @RequestHeader("userId") Long userId + @RequestHeader(name = "atk") String atk, + HttpServletRequest request ) { - Post_like post_like = postService.likePost(postId, userId); + Post_like post_like = postService.likePost(postId, request); return ApiResponse.onSuccess(PostConverter.toPostLikeRes(post_like)); } @@ -175,13 +176,14 @@ public ApiResponse likePost( }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse dislikePost( @PathVariable("post-id") Long postId, - @RequestHeader("userId") Long userId + @RequestHeader(name = "atk") String atk, + HttpServletRequest request ) { - postService.dislikePost(postId, userId); + postService.dislikePost(postId, request); return ApiResponse.onSuccess(null); } From 44911c35c4f80f0737be82eb9e1997adb4cd09a0 Mon Sep 17 00:00:00 2001 From: hjh Date: Tue, 6 Feb 2024 03:46:11 +0900 Subject: [PATCH 127/255] =?UTF-8?q?#72=20Feat:=20JWT=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=EA=B3=BC=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 2 +- .../spring/service/JwtTokenService.java | 7 ++ .../spring/service/JwtTokenServiceImpl.java | 20 ++++++ .../spring/service/PostQueryService.java | 3 +- .../spring/service/PostQueryServiceImpl.java | 6 +- .../friend/spring/service/PostService.java | 2 +- .../spring/service/PostServiceImpl.java | 4 +- .../web/controller/PostRestController.java | 68 ++++++++++++------- .../web/controller/VoteRestController.java | 38 +++++++---- 9 files changed, 108 insertions(+), 42 deletions(-) create mode 100644 src/main/java/friend/spring/service/JwtTokenService.java create mode 100644 src/main/java/friend/spring/service/JwtTokenServiceImpl.java diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index ae98f99..898d03c 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -3,6 +3,7 @@ import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; +import friend.spring.security.JwtTokenProvider; import friend.spring.service.PostQueryService; import friend.spring.web.dto.*; import org.springframework.data.domain.Page; @@ -13,7 +14,6 @@ import java.util.stream.Collectors; import friend.spring.domain.Post; import friend.spring.domain.User; -import friend.spring.domain.enums.PostCategory; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; diff --git a/src/main/java/friend/spring/service/JwtTokenService.java b/src/main/java/friend/spring/service/JwtTokenService.java new file mode 100644 index 0000000..1e34532 --- /dev/null +++ b/src/main/java/friend/spring/service/JwtTokenService.java @@ -0,0 +1,7 @@ +package friend.spring.service; + +import javax.servlet.http.HttpServletRequest; + +public interface JwtTokenService { + Long JwtToId(HttpServletRequest request); +} diff --git a/src/main/java/friend/spring/service/JwtTokenServiceImpl.java b/src/main/java/friend/spring/service/JwtTokenServiceImpl.java new file mode 100644 index 0000000..2bfbc78 --- /dev/null +++ b/src/main/java/friend/spring/service/JwtTokenServiceImpl.java @@ -0,0 +1,20 @@ +package friend.spring.service; + +import friend.spring.security.JwtTokenProvider; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletRequest; + +@Service +@RequiredArgsConstructor +public class JwtTokenServiceImpl implements JwtTokenService{ + private final JwtTokenProvider jwtTokenProvider; + @Override + @Transactional + public Long JwtToId(HttpServletRequest request){ + return jwtTokenProvider.getCurrentUser(request); + } + +} diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index aa64767..c905b20 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -5,6 +5,7 @@ import friend.spring.web.dto.PostResponseDTO; import org.springframework.data.domain.Page; +import javax.servlet.http.HttpServletRequest; import java.util.Optional; public interface PostQueryService { @@ -19,5 +20,5 @@ public interface PostQueryService { Page getReviewList(Integer page, Integer size, Integer arrange); - Page getParentPostList(Integer page,Integer size,Long userId); + Page getParentPostList(Integer page, Integer size, HttpServletRequest request); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 87d2042..465f66f 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -6,6 +6,7 @@ import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; import friend.spring.repository.*; +import friend.spring.security.JwtTokenProvider; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import lombok.RequiredArgsConstructor; @@ -18,6 +19,7 @@ import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityNotFoundException; +import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.Optional; @@ -30,6 +32,7 @@ public class PostQueryServiceImpl implements PostQueryService{ private final Gauge_VoteRepository gaugeVoteRepository; private final Card_VoteRepository cardVoteRepository; private final CategoryRepository categoryRepository; + private final JwtTokenProvider jwtTokenProvider; @Override @Transactional public Optional getPostDetail(Long postId){ @@ -110,7 +113,8 @@ public Page getReviewList(Integer page, Integer size, Integer arrange){ @Override @Transactional - public Page getParentPostList(Integer page,Integer size,Long userId){ + public Page getParentPostList(Integer page, Integer size, HttpServletRequest request){ + Long userId = jwtTokenProvider.getCurrentUser(request); Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); // List userPost = postRepository.findByUserId(userId); return postRepository.findByUserIdAndPostTypeAndState(userId, PostType.VOTE, PostState.POSTING, pageable); diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index b2759c6..6ea7900 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -20,7 +20,7 @@ public interface PostService { void checkPostLike(Boolean flag); - Post joinPost(PostRequestDTO.AddPostDTO request, Long userId); + Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2); Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user); diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index f85cf27..5a277bf 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -88,9 +88,9 @@ public void checkPostScrap(Boolean flag) { @Override @Transactional - public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { + public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2) { - + Long userId = jwtTokenProvider.getCurrentUser(request2); Post newPost= PostConverter.toPost(request); User user=userRepository.findById(userId) .orElseThrow(()->new RuntimeException("\""+userId+"\"해당 유저가 없습니다")); diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index e4fd6cd..41d966c 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -4,6 +4,7 @@ import friend.spring.converter.PostConverter; import friend.spring.domain.Post; import friend.spring.repository.PostRepository; +import friend.spring.service.JwtTokenService; import friend.spring.service.PostQueryService; import friend.spring.service.PostService; import friend.spring.web.dto.ParentPostDTO; @@ -36,9 +37,11 @@ public class PostRestController { private final PostService postService; private final PostQueryService postQueryService; private final PostRepository postRepository; - @PostMapping("/{user-id}") + private final JwtTokenService jwtTokenService; + @PostMapping("/") @Operation(summary = "글 작성 API", description = "글을 추가 합니다.") @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @Parameter(name="title", description=" 글 제목"), @Parameter(name="content", description=" 글 내용"), @Parameter(name="category", description="카테고리. 대문자(ex EDUCATION)" ), @@ -53,29 +56,38 @@ public class PostRestController { }) public ApiResponse join(@RequestBody @Valid PostRequestDTO.AddPostDTO request, - @PathVariable(name="user-id")Long UserId){ - Post post= postService.joinPost(request,UserId); + @RequestHeader("atk") String atk, + HttpServletRequest request2){ + Post post= postService.joinPost(request,request2); return ApiResponse.onSuccess(PostConverter.toAddPostResultDTO(post)); } - @GetMapping("/{user-id}/voteList") + @GetMapping("/voteList") @Operation(summary = "후기글 작성시 내투표 보기 API", description = "후기글 작성시 내투표 보기합니다.") @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), - @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)") + @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse getParentPosts(@RequestParam(name = "page", defaultValue = "0") Integer page, - @RequestParam(name = "size",defaultValue = "15") Integer size, - @RequestParam(name = "user-id") Long userId){ - Page postPage=postQueryService.getParentPostList(page,size,userId); + @RequestParam(name = "size",defaultValue = "15") Integer size, + @RequestHeader("atk") String atk, + HttpServletRequest request2){ + Page postPage=postQueryService.getParentPostList(page,size,request2); + Long userId=jwtTokenService.JwtToId(request2); return ApiResponse.onSuccess(PostConverter.parentPostGetListDTO(postPage,userId)); } - @GetMapping("/{post-id}/{user-id}") + @GetMapping("/{post-id}") @Operation(summary = "글 상세 보기 API", description = "글 상세 보기합니다.") + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) public ApiResponse getPostDetail(@PathVariable(name="post-id")Long PostId, - @PathVariable(name="user-id")Long userId){ + @RequestHeader("atk") String atk, + HttpServletRequest request2){ + Long userId=jwtTokenService.JwtToId(request2); Optional postOptional =postQueryService.getPostDetail(PostId); Post parentPost=postQueryService.ParentPost(PostId);; // Optional postOptional =postRepository.findById(PostId); @@ -84,62 +96,70 @@ public ApiResponse getPostDetail(@PathVariab return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage,userId,parentPost)); } - @GetMapping("/poll-post/{user-id}/{category}") + @GetMapping("/poll-post/{category}") @Operation(summary = "고민글 전체 보기 API", description = "글 전체 보기합니다") @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)"), - @Parameter(name = "user-id", description = "query string(RequestParam) - user id"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @Parameter(name = "category", description = "query string(RequestParam) - category(대문자). 모두 보기는 ALL") }) public ApiResponse getPostDetail(@RequestParam(name = "page", defaultValue = "0") Integer page, @RequestParam(name = "size",defaultValue = "15") Integer size, - @RequestParam(name = "user-id") Long userId, - @RequestParam(name = "category") String category){ + @RequestParam(name = "category") String category, + @RequestHeader("atk") String atk, + HttpServletRequest request2){ + Long userId=jwtTokenService.JwtToId(request2); Page postPage=postQueryService.getPostList(page,size,category); return ApiResponse.onSuccess(PostConverter.pollPostGetListDTO(postPage,userId)); } - @GetMapping("/review-post/{user-id}") + @GetMapping("/review-post") @Operation(summary = "후기글 전체 보기 API", description = "글 전체 보기합니다") @Parameters({ @Parameter(name = "arrange", description = "query string(RequestParam) - 정렬 기준 변수입니다. (0: 조회순,1: 최신순) 디폴트값 0"), @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작) 디폴트값 0"), - @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정) 디폴트값 15") + @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정) 디폴트값 15"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse getReviewDetail(@RequestParam(name="arrange", defaultValue = "0") Integer arrange, @RequestParam(name = "page", defaultValue = "0") Integer page, @RequestParam(name = "size",defaultValue = "15") Integer size, - @RequestParam(name = "user-id") Long userId){ + @RequestHeader("atk") String atk, + HttpServletRequest request2){ + Long userId=jwtTokenService.JwtToId(request2); Page postPage=postQueryService.getReviewList(page,size,arrange); return ApiResponse.onSuccess(PostConverter.reviewPostGetListDTO(postPage,userId)); } - @PatchMapping("/{post-id}/post/{user-id}/edit") + @PatchMapping("/{post-id}/post/edit") @Operation(summary = "글 수정 API", description = "댓글 수정하는 API입니다. ex) /posts/1/comment/1/edit") @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse editPost(@PathVariable("post-id") Long postId, @RequestBody PostRequestDTO.PostEditReq request, - @RequestHeader("userId") Long userId - ) { + @RequestHeader("atk") String atk, + HttpServletRequest request2) { + Long userId=jwtTokenService.JwtToId(request2); postService.editPost(postId, request, userId); return ApiResponse.onSuccess(null); } - @PatchMapping("/{post-id}/post/{user-id}/del") + @PatchMapping("/{post-id}/post/del") @Operation(summary = "댓글 삭제 API", description = "댓글 삭제하는 API입니다. ex) /posts/1/comment/1/del") @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)") + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse deleteComment( @PathVariable("post-id") Long postId, - @RequestHeader("userId") Long userId + @RequestHeader("atk") String atk, + HttpServletRequest request2 ) { + Long userId=jwtTokenService.JwtToId(request2); postService.deletePost(postId, userId); return ApiResponse.onSuccess(null); } diff --git a/src/main/java/friend/spring/web/controller/VoteRestController.java b/src/main/java/friend/spring/web/controller/VoteRestController.java index 7de47dc..a962dbd 100644 --- a/src/main/java/friend/spring/web/controller/VoteRestController.java +++ b/src/main/java/friend/spring/web/controller/VoteRestController.java @@ -5,6 +5,8 @@ import friend.spring.domain.Card_vote; import friend.spring.domain.Gauge_vote; import friend.spring.domain.General_vote; +import friend.spring.security.JwtTokenProvider; +import friend.spring.service.JwtTokenService; import friend.spring.service.VoteService; import friend.spring.web.dto.VoteRequestDTO; import friend.spring.web.dto.VoteResponseDTO; @@ -15,6 +17,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; @RestController @@ -22,39 +25,50 @@ @Validated @RequestMapping("/posts") public class VoteRestController { + private final JwtTokenService jwtTokenService; private final VoteService voteService; - @PostMapping("/{post-id}/{user-id}/generalVote") - @Operation(summary = "일반 투표 API", description = "임시로 user-id 입력") + @PostMapping("/{post-id}/generalVote") + @Operation(summary = "일반 투표 API", description = "일반 투표에 참여합니다.") @Parameters({ @Parameter(name="postId", description=" 글 id"), - @Parameter(name="selectList", description=" 투표 후보 id 리스트") + @Parameter(name="selectList", description=" 투표 후보 id 리스트"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GeneralVoteRequestDTO request, - @PathVariable(name="user-id")Long UserId){ + @RequestHeader("atk") String atk, + HttpServletRequest request2){ + Long UserId=jwtTokenService.JwtToId(request2); General_vote generalVote= voteService.castGeneralVote(request,UserId); return ApiResponse.onSuccess(VoteConverter.toAddGeneralVoteResultDTO(generalVote)); } - @PostMapping("/{post-id}/{user-id}/gaugeVote") - @Operation(summary = "게이지 투표 API", description = "임시로 user-id 입력") + @PostMapping("/{post-id}/gaugeVote") + @Operation(summary = "게이지 투표 API", description = "게이지 투표에 참여합니다") @Parameters({ @Parameter(name="postId", description=" 글 id"), - @Parameter(name="selectList", description=" 게이지") + @Parameter(name="selectList", description=" 게이지"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GaugeVoteRequestDTO request, - @PathVariable(name="user-id")Long UserId){ + @RequestHeader("atk") String atk, + HttpServletRequest request2 + ){ + Long UserId=jwtTokenService.JwtToId(request2); Gauge_vote gaugeVote= voteService.castGaugeVote(request,UserId); return ApiResponse.onSuccess(VoteConverter.toAddGaugelVoteResultDTO(gaugeVote)); } - @PostMapping("/{post-id}/{user-id}/cardVote") - @Operation(summary = "카드 투표 API", description = "임시로 user-id 입력") + @PostMapping("/{post-id}/cardVote") + @Operation(summary = "카드 투표 API", description = "카드 투표에 참여합니다.") @Parameters({ @Parameter(name="postId", description=" 글 id"), - @Parameter(name="selectList", description=" 투표 후보 id 리스트") + @Parameter(name="selectList", description=" 투표 후보 id 리스트"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.CardVoteRequestDTO request, - @PathVariable(name="user-id")Long UserId){ + @RequestHeader("atk") String atk, + HttpServletRequest request2){ + Long UserId=jwtTokenService.JwtToId(request2); Card_vote cardVote= voteService.castCardVote(request,UserId); return ApiResponse.onSuccess(VoteConverter.toAddCardVoteResultDTO(cardVote)); } From c86ce1658acbfb0cc9934bc4f0ab546e621a6df9 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Tue, 6 Feb 2024 07:56:42 +0900 Subject: [PATCH 128/255] =?UTF-8?q?#63=20Feat=20:=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=ED=95=9C=20=EA=B2=8C=EC=8B=9C=EB=AC=BC(=EB=82=B4=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC)=20API=20=EA=B5=AC=ED=98=84=20(NPE?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=ED=8F=AC=ED=95=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 3 +- .../spring/converter/MyPageConverter.java | 26 ++++++++ .../spring/repository/CategoryRepository.java | 7 ++ .../repository/PostScrapRepository.java | 15 +++++ .../friend/spring/service/MyPageService.java | 16 +++++ .../spring/service/MyPageServiceImpl.java | 64 +++++++++++++++++++ .../friend/spring/service/PostService.java | 2 + .../spring/service/PostServiceImpl.java | 7 ++ .../web/controller/MyPageController.java | 52 +++++++++++++++ .../spring/web/dto/MyPageResponseDTO.java | 19 ++++++ 10 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 src/main/java/friend/spring/converter/MyPageConverter.java create mode 100644 src/main/java/friend/spring/repository/CategoryRepository.java create mode 100644 src/main/java/friend/spring/repository/PostScrapRepository.java create mode 100644 src/main/java/friend/spring/service/MyPageService.java create mode 100644 src/main/java/friend/spring/service/MyPageServiceImpl.java create mode 100644 src/main/java/friend/spring/web/controller/MyPageController.java create mode 100644 src/main/java/friend/spring/web/dto/MyPageResponseDTO.java diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 52a9407..894e74d 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -32,7 +32,8 @@ public enum ErrorStatus implements BaseErrorCode { POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "글을 찾을 수 없습니다."), POST_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "POST4002", "올바른 사용자(글 작성자)가 아닙니다."), POST_LIKE_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4003", "글에 대한 좋아요 데이터를 찾을 수 없습니다."), - + POST_CATGORY_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4004", "카테고리를 찾을 수 없습니다."), + POST_SAVED_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4005", "저장한 글이 없습니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), COMMENT_LIKE_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4002", "댓글에 대한 좋아요 데이터를 찾을 수 없습니다."), diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java new file mode 100644 index 0000000..88d9b70 --- /dev/null +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -0,0 +1,26 @@ +package friend.spring.converter; + +import friend.spring.domain.Category; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.domain.mapping.Post_scrap; +import friend.spring.web.dto.MyPageResponseDTO; +import org.springframework.data.domain.Page; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class MyPageConverter { + + public static MyPageResponseDTO.SavedCategoryResDTO toSavedCategoryResDTO(List categoryList){ + List categoryNameList = new ArrayList<>(); + categoryNameList = categoryList.stream().map(category -> { + return category.getName(); + }).collect(Collectors.toList()); + + return MyPageResponseDTO.SavedCategoryResDTO.builder() + .postCategoryList(categoryNameList).build(); + } +} diff --git a/src/main/java/friend/spring/repository/CategoryRepository.java b/src/main/java/friend/spring/repository/CategoryRepository.java new file mode 100644 index 0000000..4eba9d0 --- /dev/null +++ b/src/main/java/friend/spring/repository/CategoryRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.Category; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CategoryRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/repository/PostScrapRepository.java b/src/main/java/friend/spring/repository/PostScrapRepository.java new file mode 100644 index 0000000..68cc5d3 --- /dev/null +++ b/src/main/java/friend/spring/repository/PostScrapRepository.java @@ -0,0 +1,15 @@ +package friend.spring.repository; + +import friend.spring.domain.Category; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.domain.mapping.Post_scrap; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface PostScrapRepository extends JpaRepository { + Page findAllByUser(User user); +} diff --git a/src/main/java/friend/spring/service/MyPageService.java b/src/main/java/friend/spring/service/MyPageService.java new file mode 100644 index 0000000..6b5c187 --- /dev/null +++ b/src/main/java/friend/spring/service/MyPageService.java @@ -0,0 +1,16 @@ +package friend.spring.service; + +import friend.spring.domain.Category; +import friend.spring.domain.Post; +import friend.spring.domain.enums.PostCategory; +import friend.spring.domain.mapping.Post_scrap; +import org.springframework.data.domain.Page; + +import java.util.List; +import java.util.Set; + +public interface MyPageService { + void checkPost(Boolean flag); + void checkScrapPost(Boolean flag); + List getScrapList(Long userId); +} diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java new file mode 100644 index 0000000..ec490d6 --- /dev/null +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -0,0 +1,64 @@ +package friend.spring.service; + +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.apiPayload.handler.PostHandler; +import friend.spring.domain.Category; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.domain.mapping.Post_scrap; +import friend.spring.repository.CategoryRepository; +import friend.spring.repository.PostScrapRepository; +import friend.spring.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +@Transactional +public class MyPageServiceImpl implements MyPageService{ + + private final UserRepository userRepository; + private final UserService userService; + private final CategoryRepository categoryRepository; + private final PostScrapRepository postScrapRepository; + @Override + public void checkPost(Boolean flag) { + if (!flag) { + throw new PostHandler(ErrorStatus.POST_CATGORY_NOT_FOUND); + } + } + @Override + public void checkScrapPost(Boolean flag) { + if (!flag) { + throw new PostHandler(ErrorStatus.POST_SAVED_NOT_FOUND); + } + } + + //저장한 게시물 + @Override + public List getScrapList(Long userId) { + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()){ + userService.checkUser(false); + } + User user = optionalUser.get(); + List postScrapList = user.getPostScrapList().stream() + .map(postScrap -> { + return postScrapRepository.findById(postScrap.getId()).orElseThrow(() -> new PostHandler(ErrorStatus.POST_SAVED_NOT_FOUND)); + }).collect(Collectors.toList()); + if (postScrapList.isEmpty()){ + checkScrapPost(false); + } + + List categoryList = postScrapList.stream().map(postScrap -> { + return postScrap.getPost().getPostCategory(); + }).collect(Collectors.toList()); + return categoryList; + } +} diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index 25643da..c4601c7 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -14,6 +14,8 @@ public interface PostService { void checkPostLike(Boolean flag); + void checkPostScrap(Boolean flag); + Post joinPost(PostRequestDTO.AddPostDTO request, Long userId); Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user); diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index c6723c7..8a6e5fc 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -67,6 +67,13 @@ public void checkPostLike(Boolean flag) { } } + @Override + public void checkPostScrap(Boolean flag) { + if (!flag){ + throw new PostHandler(ErrorStatus.POST_CATGORY_NOT_FOUND); + } + } + @Override @Transactional public Post joinPost(PostRequestDTO.AddPostDTO request, Long userId) { diff --git a/src/main/java/friend/spring/web/controller/MyPageController.java b/src/main/java/friend/spring/web/controller/MyPageController.java new file mode 100644 index 0000000..d09ef63 --- /dev/null +++ b/src/main/java/friend/spring/web/controller/MyPageController.java @@ -0,0 +1,52 @@ +package friend.spring.web.controller; + +import friend.spring.apiPayload.ApiResponse; +import friend.spring.converter.MyPageConverter; +import friend.spring.domain.Category; +import friend.spring.domain.mapping.Post_scrap; +import friend.spring.service.MyPageService; +import friend.spring.service.PostService; +import friend.spring.service.UserService; +import friend.spring.web.dto.MyPageResponseDTO; +import friend.spring.web.dto.PostResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Set; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/user/my-page") +public class MyPageController { + private UserService userService; + private PostService postService; + private MyPageService myPageService; + + //저장한 게시물(내 카테고리) 조회 + @GetMapping("/post") + @Operation(summary = "사용자 글 카테고리 조회 API",description = "사용자의 저장 글 카테고리 목록을 집합으로 조회하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "회원정보가 존재하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004",description = "카테고리를 찾을 수 없습니다.") + + }) + @Parameters({ + @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)") + }) + public ApiResponse getCategorySet( + @RequestHeader(name = "userId") Long userId){ + List scrapList = myPageService.getScrapList(userId); + return ApiResponse.onSuccess(MyPageConverter.toSavedCategoryResDTO(scrapList)); + } + +} diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java new file mode 100644 index 0000000..421a36f --- /dev/null +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -0,0 +1,19 @@ +package friend.spring.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Set; + +public class MyPageResponseDTO { + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class SavedCategoryResDTO{ + List postCategoryList; + } +} From de120f439b87035ae8ad61c827928f8b9f76b223 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Tue, 6 Feb 2024 08:13:03 +0900 Subject: [PATCH 129/255] =?UTF-8?q?#77=20Feat=20:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=ED=86=A0=ED=81=B0=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/AlarmRestController.java | 7 +++- .../web/controller/UserRestController.java | 36 ++++++++++++++----- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/main/java/friend/spring/web/controller/AlarmRestController.java b/src/main/java/friend/spring/web/controller/AlarmRestController.java index dae56b4..08c9510 100644 --- a/src/main/java/friend/spring/web/controller/AlarmRestController.java +++ b/src/main/java/friend/spring/web/controller/AlarmRestController.java @@ -4,6 +4,7 @@ import friend.spring.converter.AlarmConverter; import friend.spring.domain.Alarm; import friend.spring.service.AlarmService; +import friend.spring.service.JwtTokenService; import friend.spring.web.dto.AlarmResponseDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -15,12 +16,15 @@ import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; + @RestController @RequiredArgsConstructor @RequestMapping("/user") public class AlarmRestController { private final AlarmService alarmService; + private final JwtTokenService jwtTokenService; //알림 조회 @GetMapping("/alarm") @Operation(summary = "사용자 알림 조회 API",description = "사용자의 알림 목록을 조회하는 API이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요") @@ -33,8 +37,9 @@ public class AlarmRestController { @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)") }) private ApiResponse getAlarm( - @RequestHeader(name = "id") Long userId, + HttpServletRequest request, @RequestParam(name = "page") Integer page){ + Long userId=jwtTokenService.JwtToId(request); Page alarmList = alarmService.getAlarmList(userId, page); return ApiResponse.onSuccess(AlarmConverter.toAlarmListResDTO(alarmList)); } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index df3e863..700292a 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -9,11 +9,7 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.repository.UserRepository; -import friend.spring.service.CommentService; -import friend.spring.service.EmailService; -import friend.spring.service.PostService; -import friend.spring.service.UserService; -import friend.spring.service.UserServiceImpl; +import friend.spring.service.*; import friend.spring.web.dto.AlarmResponseDTO; import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; @@ -22,6 +18,7 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; @@ -41,11 +38,12 @@ public class UserRestController { private final EmailService mailService; private final PostService postService; private final CommentService commentService; - + private final JwtTokenService jwtTokenService; //마이 페이지 조회 @GetMapping("/my-page") public ApiResponse getMyPage( - @RequestHeader(name = "id") Long userId) { + HttpServletRequest request) { + Long userId=jwtTokenService.JwtToId(request); User myPage = userService.findMyPage(userId); return ApiResponse.onSuccess(UserConverter.toMypageResDTO(myPage)); } @@ -67,9 +65,19 @@ public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailS //나의 Q&A 질문 조회 @GetMapping("/my-page/profile/question") + @Operation(summary = "나의 Q&A 질문 조회 API",description = "사용자의 나의 Q&A 질문 조회 API 이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + + }) + @Parameters({ + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)") + }) public ApiResponse getQuestion( - @RequestHeader(name = "id") Long userId, + HttpServletRequest request, @RequestParam(name = "page") Integer page){ + Long userId=jwtTokenService.JwtToId(request); User myPage = userService.findMyPage(userId); Level nxtLevel = userService.nextLevel(userId); Page myPostList = postService.getMyPostList(userId, page); @@ -79,9 +87,19 @@ public ApiResponse getQuestion( //나의 Q&A 답변 조회 @GetMapping("/my-page/profile/answer") + @Operation(summary = "나의 Q&A 답변 조회 API",description = "사용자의 Q&A 답변 조회 API 이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + + }) + @Parameters({ + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)") + }) public ApiResponse getAnswer( - @RequestHeader(name = "id") Long userId, + HttpServletRequest request, @RequestParam(name = "page") Integer page){ + Long userId=jwtTokenService.JwtToId(request); User myPage = userService.findMyPage(userId); Level nxtLevel = userService.nextLevel(userId); Page myCommentList = commentService.getMyCommentList(userId, page); From f23d1f7bc7f339eea0ab01b6cc94fee262fd214a Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 6 Feb 2024 10:41:03 +0900 Subject: [PATCH 130/255] =?UTF-8?q?#23=20Refactor:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EA=B2=80=EC=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 2 ++ .../spring/service/CommentServiceImpl.java | 23 +++++++++++++++---- .../spring/service/PostServiceImpl.java | 13 ++++++----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 0163d9c..0fa1400 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -33,6 +33,7 @@ public enum ErrorStatus implements BaseErrorCode { POST_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "POST4002", "올바른 사용자(글 작성자)가 아닙니다."), POST_LIKE_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4003", "글에 대한 좋아요 데이터를 찾을 수 없습니다."), POST_SCRAP_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4004", "글에 대한 스크랩 데이터를 찾을 수 없습니다."), + COMMENT_LIKE_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4005", "글에 대한 좋아요 데이터가 이미 존재합니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), @@ -40,6 +41,7 @@ public enum ErrorStatus implements BaseErrorCode { COMMENT_CHOICE_OVER_ONE(HttpStatus.BAD_REQUEST, "COMMENT4003", "댓글 채택은 1개 댓글에 대해서만 가능합니다."), COMMENT_SELECT_MYSELF(HttpStatus.BAD_REQUEST, "COMMENT4004", "자기 자신은 채택할 수 없습니다."), COMMENT_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "COMMENT4005", "올바른 사용자(댓글 작성자)가 아닙니다."), + COMMENT_POST_NOT_MATCH(HttpStatus.BAD_REQUEST, "COMMENT4006", "해당 글에 작성된 댓글이 아닙니다."), // 알림 관련 응답 ALARM_NOT_FOUND(HttpStatus.NOT_FOUND, "ALARM4001", "알림이 없습니다"), diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index cd03927..69b6e62 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -25,6 +25,8 @@ import java.util.*; import java.util.stream.Collectors; +import static friend.spring.apiPayload.code.status.ErrorStatus.*; + @Service @RequiredArgsConstructor @Transactional(readOnly = false) @@ -42,35 +44,37 @@ public class CommentServiceImpl implements CommentService { @Override public void checkComment(Boolean flag) { if (!flag) { - throw new CommentHandler(ErrorStatus.COMMENT_NOT_FOUND); + throw new CommentHandler(COMMENT_NOT_FOUND); } } @Override public void checkCommentLike(Boolean flag) { if (!flag) { - throw new CommentHandler(ErrorStatus.COMMENT_LIKE_NOT_FOUND); + throw new CommentHandler(COMMENT_LIKE_NOT_FOUND); + } else { + throw new CommentHandler(COMMENT_LIKE_DUPLICATE); } } @Override public void checkCommentChoice(Boolean flag) { if (!flag) { - throw new CommentHandler(ErrorStatus.COMMENT_CHOICE_OVER_ONE); + throw new CommentHandler(COMMENT_CHOICE_OVER_ONE); } } @Override public void checkSelectCommentAnotherUser(Boolean flag) { if (!flag) { - throw new CommentHandler(ErrorStatus.COMMENT_SELECT_MYSELF); + throw new CommentHandler(COMMENT_SELECT_MYSELF); } } @Override public void checkCommentWriterUser(Boolean flag) { if (!flag) { - throw new CommentHandler(ErrorStatus.COMMENT_NOT_CORRECT_USER); + throw new CommentHandler(COMMENT_NOT_CORRECT_USER); } } @@ -131,6 +135,15 @@ public Comment_like likeComment(Long postId, Long commentId, HttpServletRequest Comment comment = optionalComment.get(); User user = optionalUser.get(); + if (!Objects.equals(comment.getPost().getId(), post.getId())) { + throw new CommentHandler(COMMENT_POST_NOT_MATCH); + } + + Optional optionalComment_like = commentLikeRepository.findByCommentIdAndUserId(commentId, userId); + if (!optionalComment_like.isEmpty()) { + this.checkCommentLike(true); + } + Comment_like comment_like = CommentConverter.toCommentLike(post, comment, user); return commentLikeRepository.save(comment_like); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 5fbb71b..93847b4 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -27,6 +27,7 @@ import java.util.function.Function; import java.util.stream.Collectors; +import static friend.spring.apiPayload.code.status.ErrorStatus.*; import static friend.spring.domain.enums.PostType.*; import static friend.spring.domain.enums.PostVoteType.*; @@ -53,14 +54,14 @@ public class PostServiceImpl implements PostService{ @Override public void checkPost(Boolean flag) { if (!flag) { - throw new PostHandler(ErrorStatus.POST_NOT_FOUND); + throw new PostHandler(POST_NOT_FOUND); } } @Override public void checkPostWriterUser(Boolean flag) { if (!flag) { - throw new PostHandler(ErrorStatus.POST_NOT_CORRECT_USER); + throw new PostHandler(POST_NOT_CORRECT_USER); } } @@ -75,14 +76,14 @@ public Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user) { @Override public void checkPostLike(Boolean flag) { if (!flag) { - throw new PostHandler(ErrorStatus.POST_LIKE_NOT_FOUND); + throw new PostHandler(POST_LIKE_NOT_FOUND); } } @Override public void checkPostScrap(Boolean flag) { if (!flag) { - throw new PostHandler(ErrorStatus.POST_SCRAP_NOT_FOUND); + throw new PostHandler(POST_SCRAP_NOT_FOUND); } } @@ -221,7 +222,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque @Transactional public void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId){ User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); - Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); if(!user.getId().equals(post.getUser().getId())){ throw new RuntimeException("수정 권환이 없습니다 글이 없습니다"); } @@ -234,7 +235,7 @@ public void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId @Transactional public void deletePost(Long postId, Long userId) { User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); - Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); if(!user.getId().equals(post.getUser().getId())){ throw new RuntimeException("삭제 권환이 없습니다 글이 없습니다"); } From 6d6826f25d6ad2ef99ef226575419b8e488f4bae Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 6 Feb 2024 10:49:54 +0900 Subject: [PATCH 131/255] =?UTF-8?q?#23=20Refactor:=20DeleteMapping?= =?UTF-8?q?=EC=9D=B8=20=EA=B2=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/web/controller/CommentRestController.java | 2 +- .../friend/spring/web/controller/PostRestController.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 418dc26..2a11fca 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -77,7 +77,7 @@ public ApiResponse likeComment( } // 댓글 추천(좋아요) 해제 - @PostMapping("/{post-id}/comment/{comment-id}/like/del") + @DeleteMapping("/{post-id}/comment/{comment-id}/like/del") @Operation(summary = "댓글 추천(좋아요) 해제 API", description = "댓글 추천(좋아요) 해제하는 API입니다. ex) /posts/1/comment/1/like/del") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index ca4531c..5b380f7 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -149,7 +149,7 @@ public ApiResponse editPost(@PathVariable("post-id") Long postId, } @PatchMapping("/{post-id}/post/del") - @Operation(summary = "댓글 삭제 API", description = "댓글 삭제하는 API입니다. ex) /posts/1/comment/1/del") + @Operation(summary = "글 삭제 API", description = "글 삭제하는 API입니다. ex) /posts/1/del") @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @@ -186,7 +186,7 @@ public ApiResponse likePost( } // 글 추천(좋아요) 해제 - @PostMapping("/{post-id}/like/del") + @DeleteMapping("/{post-id}/like/del") @Operation(summary = "글 추천(좋아요) 해제 API", description = "글 추천(좋아요) 해제하는 API입니다. ex) /posts/1/like/del") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), @@ -263,7 +263,7 @@ public ApiResponse createScrapPost( } // 글 스크랩 해제 - @PostMapping("/{post-id}/scrap/del") + @DeleteMapping("/{post-id}/scrap/del") @Operation(summary = "글 스크랩 해제 API", description = "글 스크랩 해제하는 API입니다. ex) /posts/1/scrap/del") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), From b8b15ec9836d74c57bb4420a813c58232e1b8c69 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 6 Feb 2024 11:11:57 +0900 Subject: [PATCH 132/255] =?UTF-8?q?#80=20Refactor:=20User=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EA=B8=B0=EB=8A=A5=20swagger=20=EA=B0=84=EB=8B=A8?= =?UTF-8?q?=20=EC=84=A4=EB=AA=85=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/web/controller/UserRestController.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index df3e863..de979b8 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -51,6 +51,7 @@ public ApiResponse getMyPage( } @PostMapping ("/mailSend")//이메일 인증 코드 전송 + @Operation(summary = "이메일 인증 코드 전송 API",description = "이메일 인증 코드 전송하는 API입니다.") public ApiResponse mailSend(@RequestBody @Valid UserRequestDTO.EmailSendReq emailDto){ System.out.println("이메일 인증 요청이 들어옴"); System.out.println("이메일 인증 이메일 :"+emailDto.getEmail()); @@ -59,6 +60,7 @@ public ApiResponse mailSend(@RequestBody @Valid Us return ApiResponse.onSuccess(UserConverter.toEmailSendRes(code)); } @PostMapping("/mailauthCheck")//이메일 코드 확인 + @Operation(summary = "이메일 코드 확인 API",description = "이메일 코드 확인하는 API입니다.") public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailSendCheckReq emailSendCheckReq){ mailService.CheckAuthNum(emailSendCheckReq.getEmail(), emailSendCheckReq.getAuthNum()); @@ -88,6 +90,7 @@ public ApiResponse getAnswer( return ApiResponse.onSuccess(UserConverter.toAnswerResDTO(myPage, nxtLevel, myCommentList)); } @PostMapping("/join")//회원가입 + @Operation(summary = "회원가입 API",description = "회원가입하는 API입니다.") public ApiResponse join(@RequestBody @Valid UserRequestDTO.UserJoinRequest userJoinRequest) { User user = userService.joinUser(userJoinRequest); @@ -97,6 +100,7 @@ public ApiResponse join(@RequestBody @Valid UserR //로그인 @PostMapping("/login") + @Operation(summary = "로그인 API",description = "로그인하는 API입니다.") public ApiResponse> login(@RequestBody UserRequestDTO.UserLoginRequest userLoginRequest)throws GeneralException{ List tokenDTOList = userService.login(userLoginRequest); return ApiResponse.onSuccess(tokenDTOList); @@ -104,6 +108,7 @@ public ApiResponse> login(@RequestBody UserRequestDTO.UserLoginRe // 토큰 재발급 @PostMapping("/reissue") + @Operation(summary = "토큰 재발급 API",description = "토큰 재발급하는 API입니다.") public ApiResponse> reissue(@RequestHeader(name = "rtk") String rtk, HttpServletRequest request) { System.out.println("controller: reissue 함수 실행"); return ApiResponse.onSuccess(userService.reissue(request)); @@ -111,6 +116,7 @@ public ApiResponse> reissue(@RequestHeader(name = "rtk") String r // 로그아웃 @PostMapping("/logout") + @Operation(summary = "로그아웃 API",description = "로그아웃하는 API입니다.") public ApiResponse logout(@RequestHeader(name = "atk") String atk, HttpServletRequest request) { return ApiResponse.onSuccess(userService.logout(request)); } From 8a880b9f20e666ee2376bcbae3813e8e5eda2223 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 6 Feb 2024 11:15:04 +0900 Subject: [PATCH 133/255] =?UTF-8?q?#77=20Refactor:=20RequestHeader=20atk?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/web/controller/AlarmRestController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/friend/spring/web/controller/AlarmRestController.java b/src/main/java/friend/spring/web/controller/AlarmRestController.java index 08c9510..b0b26d0 100644 --- a/src/main/java/friend/spring/web/controller/AlarmRestController.java +++ b/src/main/java/friend/spring/web/controller/AlarmRestController.java @@ -37,6 +37,7 @@ public class AlarmRestController { @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)") }) private ApiResponse getAlarm( + @RequestHeader(name = "atk") String atk, HttpServletRequest request, @RequestParam(name = "page") Integer page){ Long userId=jwtTokenService.JwtToId(request); From cd3cbd6896f605d4967e3510a5b03013e53906cb Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 6 Feb 2024 11:15:13 +0900 Subject: [PATCH 134/255] =?UTF-8?q?#77=20Refactor:=20RequestHeader=20atk?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/web/controller/UserRestController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 700292a..b382a41 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -42,6 +42,7 @@ public class UserRestController { //마이 페이지 조회 @GetMapping("/my-page") public ApiResponse getMyPage( + @RequestHeader(name = "atk") String atk, HttpServletRequest request) { Long userId=jwtTokenService.JwtToId(request); User myPage = userService.findMyPage(userId); From e4a815858275753b426862fa722af6772a40305f Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 6 Feb 2024 11:33:43 +0900 Subject: [PATCH 135/255] =?UTF-8?q?#80=20Refactor:=20User=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EA=B8=B0=EB=8A=A5=20swagger=20=EA=B0=84=EB=8B=A8?= =?UTF-8?q?=20=EC=84=A4=EB=AA=85=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/UserRestController.java | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index de979b8..484e610 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -2,7 +2,6 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.apiPayload.GeneralException; -import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.converter.UserConverter; import friend.spring.domain.Comment; import friend.spring.domain.Level; @@ -13,15 +12,13 @@ import friend.spring.service.EmailService; import friend.spring.service.PostService; import friend.spring.service.UserService; -import friend.spring.service.UserServiceImpl; -import friend.spring.web.dto.AlarmResponseDTO; import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; import friend.spring.web.dto.UserResponseDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; @@ -52,6 +49,10 @@ public ApiResponse getMyPage( @PostMapping ("/mailSend")//이메일 인증 코드 전송 @Operation(summary = "이메일 인증 코드 전송 API",description = "이메일 인증 코드 전송하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + }) + @Parameters({ }) public ApiResponse mailSend(@RequestBody @Valid UserRequestDTO.EmailSendReq emailDto){ System.out.println("이메일 인증 요청이 들어옴"); System.out.println("이메일 인증 이메일 :"+emailDto.getEmail()); @@ -61,10 +62,14 @@ public ApiResponse mailSend(@RequestBody @Valid Us } @PostMapping("/mailauthCheck")//이메일 코드 확인 @Operation(summary = "이메일 코드 확인 API",description = "이메일 코드 확인하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005",description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), + }) + @Parameters({ }) public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailSendCheckReq emailSendCheckReq){ - - mailService.CheckAuthNum(emailSendCheckReq.getEmail(), emailSendCheckReq.getAuthNum()); - return ApiResponse.onSuccess(null); + mailService.CheckAuthNum(emailSendCheckReq.getEmail(), emailSendCheckReq.getAuthNum()); + return ApiResponse.onSuccess(null); } //나의 Q&A 질문 조회 @@ -91,6 +96,11 @@ public ApiResponse getAnswer( } @PostMapping("/join")//회원가입 @Operation(summary = "회원가입 API",description = "회원가입하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4002",description = "NOT_ACCEPTABLE, 이미 존재하는 메일 주소입니다."), + }) + @Parameters({ }) public ApiResponse join(@RequestBody @Valid UserRequestDTO.UserJoinRequest userJoinRequest) { User user = userService.joinUser(userJoinRequest); @@ -101,6 +111,11 @@ public ApiResponse join(@RequestBody @Valid UserR //로그인 @PostMapping("/login") @Operation(summary = "로그인 API",description = "로그인하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4010",description = "NOT_FOUND, 가입 가능한 이메일입니다.(이메일 정보가 존재하지 않습니다.)"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4008",description = "NOT_FOUND, 비밀번호가 틀렸습니다."), + }) public ApiResponse> login(@RequestBody UserRequestDTO.UserLoginRequest userLoginRequest)throws GeneralException{ List tokenDTOList = userService.login(userLoginRequest); return ApiResponse.onSuccess(tokenDTOList); @@ -109,6 +124,14 @@ public ApiResponse> login(@RequestBody UserRequestDTO.UserLoginRe // 토큰 재발급 @PostMapping("/reissue") @Operation(summary = "토큰 재발급 API",description = "토큰 재발급하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4007",description = "UNAUTHORIZED, 유효하지 않은 JWT입니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4100",description = "UNAUTHORIZED, RefreshToken값을 확인해주세요."), + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) public ApiResponse> reissue(@RequestHeader(name = "rtk") String rtk, HttpServletRequest request) { System.out.println("controller: reissue 함수 실행"); return ApiResponse.onSuccess(userService.reissue(request)); @@ -117,6 +140,13 @@ public ApiResponse> reissue(@RequestHeader(name = "rtk") String r // 로그아웃 @PostMapping("/logout") @Operation(summary = "로그아웃 API",description = "로그아웃하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 회원정보가 존재하지 않습니다."), + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) public ApiResponse logout(@RequestHeader(name = "atk") String atk, HttpServletRequest request) { return ApiResponse.onSuccess(userService.logout(request)); } From 9bc2ef167ee1b2a5af1e4f2aa52bfc39c8b887a3 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 6 Feb 2024 13:03:28 +0900 Subject: [PATCH 136/255] =?UTF-8?q?#80=20Refactor:=20=EB=82=98=EC=9D=98=20?= =?UTF-8?q?Q&A=20=EC=A7=88=EB=AC=B8/=EB=8B=B5=EB=B3=80=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20RequestHeader=20atk=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/web/controller/UserRestController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 35b1b88..46257f8 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -89,6 +89,7 @@ public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailS @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)") }) public ApiResponse getQuestion( + @RequestHeader(name = "atk") String atk, HttpServletRequest request, @RequestParam(name = "page") Integer page){ Long userId=jwtTokenService.JwtToId(request); @@ -111,7 +112,8 @@ public ApiResponse getQuestion( @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)") }) public ApiResponse getAnswer( - HttpServletRequest request, + @RequestHeader(name = "atk") String atk, + HttpServletRequest request, @RequestParam(name = "page") Integer page){ Long userId=jwtTokenService.JwtToId(request); User myPage = userService.findMyPage(userId); From 412d2986d5979d45e60b694f64292db520f6e990 Mon Sep 17 00:00:00 2001 From: hjh Date: Tue, 6 Feb 2024 17:39:39 +0900 Subject: [PATCH 137/255] =?UTF-8?q?#83=20Feat:=20=EA=B8=80=20=EA=B8=80?= =?UTF-8?q?=EC=93=B4=EC=9D=B4=20=ED=99=95=EC=9D=B8,=20swagger=20=EC=84=A4?= =?UTF-8?q?=EB=AA=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/converter/PostConverter.java | 8 ++++++++ .../friend/spring/service/PostQueryServiceImpl.java | 2 +- .../spring/web/controller/PostRestController.java | 12 ++++++------ .../java/friend/spring/web/dto/PostResponseDTO.java | 1 + 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 898d03c..f764284 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -195,12 +195,16 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, Boolean engage,Long userId, Post parentPost){ Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); + Boolean myPost=false; List userChoiceList=null; List percent=null; List voteResult=null; Integer value=null; Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + if(post.getUser().getId().equals(userId)){ + myPost=true; + } if(post.getPostType()==REVIEW){ @@ -216,6 +220,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .comment(commentCount) .isLike(isLike) .isComment(isComment) + .myPost(myPost) .build(); } if(post.getVoteType()==PostVoteType.GAUGE){ @@ -236,6 +241,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .comment(commentCount) .isLike(isLike) .isComment(isComment) + .myPost(myPost) .build(); } if(post.getVoteType()==PostVoteType.GENERAL){ @@ -303,6 +309,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .comment(commentCount) .isLike(isLike) .isComment(isComment) + .myPost(myPost) .build(); } List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() @@ -369,6 +376,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .comment(commentCount) .isLike(isLike) .isComment(isComment) + .myPost(myPost) .build(); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 465f66f..21108d2 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -92,7 +92,7 @@ public Optional findPost(Long postId) { @Override @Transactional public Page getPostList(Integer page,Integer size,String category){ - if(category=="ALL"){ + if(category.equals("모두")){ Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); return postRepository.findByPostTypeAndState(PostType.VOTE, PostState.POSTING, pageable);} Category category1 = categoryRepository.findByName(category); diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 41d966c..19ee9d6 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -44,7 +44,7 @@ public class PostRestController { @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @Parameter(name="title", description=" 글 제목"), @Parameter(name="content", description=" 글 내용"), - @Parameter(name="category", description="카테고리. 대문자(ex EDUCATION)" ), + @Parameter(name="category", description="카테고리. 한글 입력(ex 교육)" ), @Parameter(name="postType", description=" 글 종류
1 : VOTE
2 : REVIEW"), @Parameter(name="postVoteType", description=" 투표 종류
1 : GENERAL
2 : GAUGE
3 : CARD
해당 사항 없을시 null"), @Parameter(name="pollTitle", description=" 투표 제목"), @@ -80,7 +80,8 @@ public ApiResponse getParentPosts(@RequestPa } @GetMapping("/{post-id}") - @Operation(summary = "글 상세 보기 API", description = "글 상세 보기합니다.") + @Operation(summary = "글 상세 보기 API", description = "글 상세 보기합니다
response로 나오는 isLike, isComment는 각각 조회하는 사용자의 좋아요 클릭 여부, " + + "댓글 작성 여부입니다..") @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) @@ -90,7 +91,6 @@ public ApiResponse getPostDetail(@PathVariab Long userId=jwtTokenService.JwtToId(request2); Optional postOptional =postQueryService.getPostDetail(PostId); Post parentPost=postQueryService.ParentPost(PostId);; -// Optional postOptional =postRepository.findById(PostId); Boolean engage=postQueryService.checkEngage(PostId,userId); Post post = postOptional.get(); return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage,userId,parentPost)); @@ -102,7 +102,7 @@ public ApiResponse getPostDetail(@PathVariab @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), - @Parameter(name = "category", description = "query string(RequestParam) - category(대문자). 모두 보기는 ALL") + @Parameter(name = "category", description = "query string(RequestParam) - category(한글). 모두 보기는 '모두'라고 입력 하시면 됩니다.") }) public ApiResponse getPostDetail(@RequestParam(name = "page", defaultValue = "0") Integer page, @RequestParam(name = "size",defaultValue = "15") Integer size, @@ -133,7 +133,7 @@ public ApiResponse getReviewDetail(@Reques return ApiResponse.onSuccess(PostConverter.reviewPostGetListDTO(postPage,userId)); } - @PatchMapping("/{post-id}/post/edit") + @PatchMapping("/{post-id}/edit") @Operation(summary = "글 수정 API", description = "댓글 수정하는 API입니다. ex) /posts/1/comment/1/edit") @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @@ -148,7 +148,7 @@ public ApiResponse editPost(@PathVariable("post-id") Long postId, return ApiResponse.onSuccess(null); } - @PatchMapping("/{post-id}/post/del") + @PatchMapping("/{post-id}/del") @Operation(summary = "댓글 삭제 API", description = "댓글 삭제하는 API입니다. ex) /posts/1/comment/1/del") @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 252f03a..fdc6f56 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -45,6 +45,7 @@ public static class PostDetailResponse { Integer comment; Boolean isLike; Boolean isComment; + Boolean myPost; } From 7bde24331690306809051dd73efcf237305251d8 Mon Sep 17 00:00:00 2001 From: hjh Date: Tue, 6 Feb 2024 22:19:11 +0900 Subject: [PATCH 138/255] =?UTF-8?q?#83=20Feat:=20=ED=88=AC=ED=91=9C=20api?= =?UTF-8?q?=20=EA=B2=BD=EB=A1=9C=20=EC=9E=AC=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/service/VoteService.java | 6 ++--- .../spring/service/VoteServiceImpl.java | 22 +++++++++---------- .../web/controller/VoteRestController.java | 14 ++++++------ .../friend/spring/web/dto/VoteRequestDTO.java | 3 --- 4 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/main/java/friend/spring/service/VoteService.java b/src/main/java/friend/spring/service/VoteService.java index 9254fce..58ce80a 100644 --- a/src/main/java/friend/spring/service/VoteService.java +++ b/src/main/java/friend/spring/service/VoteService.java @@ -7,9 +7,9 @@ public interface VoteService { - General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId); - Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long userId); + General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request,Long PostId, Long userId); + Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request,Long PostId, Long userId); - Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request, Long userId); + Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request, Long PostId, Long userId); } diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index ff07493..92946bb 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -24,14 +24,14 @@ public class VoteServiceImpl implements VoteService{ private final Gauge_PollRepository gaugePollRepository; @Override @Transactional - public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long userId) { + public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long PostId, Long userId) { General_vote newGeneralVote = VoteConverter.toGeneralVote(request); User user = userRepository.findById(userId) .orElseThrow(() -> new RuntimeException("\"" + userId + "\"해당 유저가 없습니다")); newGeneralVote.setUser(user); - Post post=postRepository.findById(request.getPostId()) - .orElseThrow(()-> new RuntimeException("\"" + request.getPostId() + "\"해당 글이 없습니다")); + Post post=postRepository.findById(PostId) + .orElseThrow(()-> new RuntimeException("\"" + PostId + "\"해당 글이 없습니다")); General_poll generalPoll=post.getGeneralPoll(); newGeneralVote.setGeneralPoll(generalPoll); @@ -63,14 +63,14 @@ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request @Override @Transactional - public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long userId){ + public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long PostId, Long userId){ Gauge_vote newGaugeVote = VoteConverter.toGaugeVote(request); User user = userRepository.findById(userId) .orElseThrow(() -> new RuntimeException("\"" + userId + "\"해당 유저가 없습니다")); newGaugeVote.setUser(user); - Post post=postRepository.findById(request.getPostId()) - .orElseThrow(()-> new RuntimeException("\"" + request.getPostId() + "\"해당 글이 없습니다")); + Post post=postRepository.findById(PostId) + .orElseThrow(()-> new RuntimeException("\"" + PostId + "\"해당 글이 없습니다")); Gauge_poll gaugePoll=post.getGaugePoll(); newGaugeVote.setGaugePoll(gaugePoll); @@ -84,8 +84,8 @@ public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long pointRepository.save(newPoint); Integer value=request.getValue(); - gaugePollRepository.findById(request.getPostId()); - Optional optionalPost=postRepository.findById(request.getPostId()); + gaugePollRepository.findById(PostId); + Optional optionalPost=postRepository.findById(PostId); Post gaugePost=optionalPost.get(); Integer currentGauge=gaugePost.getGaugePoll().getGauge(); Integer engagedUser=gaugePost.getGaugePoll().getGaugeVoteList().size(); @@ -96,14 +96,14 @@ public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long } @Override @Transactional - public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request, Long userId){ + public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request,Long PostId, Long userId){ Card_vote newCardVote = VoteConverter.toCardVote(request); User user = userRepository.findById(userId) .orElseThrow(() -> new RuntimeException("\"" + userId + "\"해당 유저가 없습니다")); newCardVote.setUser(user); - Post post=postRepository.findById(request.getPostId()) - .orElseThrow(()-> new RuntimeException("\"" + request.getPostId() + "\"해당 글이 없습니다")); + Post post=postRepository.findById(PostId) + .orElseThrow(()-> new RuntimeException("\"" + PostId + "\"해당 글이 없습니다")); Card_poll cardPoll=post.getCardPoll(); newCardVote.setCardPoll(cardPoll); diff --git a/src/main/java/friend/spring/web/controller/VoteRestController.java b/src/main/java/friend/spring/web/controller/VoteRestController.java index a962dbd..2e850c3 100644 --- a/src/main/java/friend/spring/web/controller/VoteRestController.java +++ b/src/main/java/friend/spring/web/controller/VoteRestController.java @@ -30,46 +30,46 @@ public class VoteRestController { @PostMapping("/{post-id}/generalVote") @Operation(summary = "일반 투표 API", description = "일반 투표에 참여합니다.") @Parameters({ - @Parameter(name="postId", description=" 글 id"), @Parameter(name="selectList", description=" 투표 후보 id 리스트"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GeneralVoteRequestDTO request, + @PathVariable(name="post-id")Long PostId, @RequestHeader("atk") String atk, HttpServletRequest request2){ Long UserId=jwtTokenService.JwtToId(request2); - General_vote generalVote= voteService.castGeneralVote(request,UserId); + General_vote generalVote= voteService.castGeneralVote(request,PostId,UserId); return ApiResponse.onSuccess(VoteConverter.toAddGeneralVoteResultDTO(generalVote)); } @PostMapping("/{post-id}/gaugeVote") @Operation(summary = "게이지 투표 API", description = "게이지 투표에 참여합니다") @Parameters({ - @Parameter(name="postId", description=" 글 id"), - @Parameter(name="selectList", description=" 게이지"), + @Parameter(name="gauge", description=" 게이지"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GaugeVoteRequestDTO request, + @PathVariable(name="post-id")Long PostId, @RequestHeader("atk") String atk, HttpServletRequest request2 ){ Long UserId=jwtTokenService.JwtToId(request2); - Gauge_vote gaugeVote= voteService.castGaugeVote(request,UserId); + Gauge_vote gaugeVote= voteService.castGaugeVote(request,PostId,UserId); return ApiResponse.onSuccess(VoteConverter.toAddGaugelVoteResultDTO(gaugeVote)); } @PostMapping("/{post-id}/cardVote") @Operation(summary = "카드 투표 API", description = "카드 투표에 참여합니다.") @Parameters({ - @Parameter(name="postId", description=" 글 id"), @Parameter(name="selectList", description=" 투표 후보 id 리스트"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.CardVoteRequestDTO request, + @PathVariable(name="post-id")Long PostId, @RequestHeader("atk") String atk, HttpServletRequest request2){ Long UserId=jwtTokenService.JwtToId(request2); - Card_vote cardVote= voteService.castCardVote(request,UserId); + Card_vote cardVote= voteService.castCardVote(request,PostId,UserId); return ApiResponse.onSuccess(VoteConverter.toAddCardVoteResultDTO(cardVote)); } } diff --git a/src/main/java/friend/spring/web/dto/VoteRequestDTO.java b/src/main/java/friend/spring/web/dto/VoteRequestDTO.java index e7c856c..63cc7a9 100644 --- a/src/main/java/friend/spring/web/dto/VoteRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/VoteRequestDTO.java @@ -9,19 +9,16 @@ public class VoteRequestDTO { @Getter public static class GeneralVoteRequestDTO{ - Long postId; List selectList; } @Getter public static class GaugeVoteRequestDTO{ - Long postId; Integer value; } @Getter public static class CardVoteRequestDTO{ - Long postId; List selectList; } } From fb2926afb6906a2e848aa3f1ed0c9ca908f32d8a Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 7 Feb 2024 04:46:20 +0900 Subject: [PATCH 139/255] =?UTF-8?q?#83=20Feat:=20=EA=B8=80=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=EB=B3=B4=EA=B8=B0=20=ED=9B=84=EA=B8=B0=EC=9D=98=20?= =?UTF-8?q?=ED=88=AC=ED=91=9C=EA=B2=B0=EA=B3=BC=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=ED=9B=84?= =?UTF-8?q?=EB=B3=B4=EC=9D=B4=EB=A6=84,=20=EB=A7=81=ED=81=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 32 ++++++++++++++++++- .../spring/service/PostServiceImpl.java | 3 ++ .../web/controller/PostRestController.java | 2 +- .../friend/spring/web/dto/ParentPollDTO.java | 2 ++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index f764284..f14ece8 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -3,6 +3,7 @@ import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; +import friend.spring.repository.CandidateRepository; import friend.spring.security.JwtTokenProvider; import friend.spring.service.PostQueryService; import friend.spring.web.dto.*; @@ -77,6 +78,7 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ // 선택률 -> ParentPollDTO 객체 리스트로 변환 List candidateInfos = candidateSelectionCounts.entrySet().stream() .map(entry -> ParentPollDTO.builder() +// .candidateName(candidateRepository.findById(entry.getKey()).orElseThrow(()->new RuntimeException("없으요")).getName()) .candidateId(entry.getKey()) .rate((int) ((double) entry.getValue() / totalVotes * 100)) .selection(entry.getValue()) @@ -91,7 +93,20 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ if(highestSelectionCandidate.isPresent()) { parentPollDTO = highestSelectionCandidate.get(); } - + // 1등 후보 이름, 사진 반환 + Long id=parentPollDTO.getCandidateId(); + Optional name = parentPost.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> candidate.getId().equals(id)) + .map(Candidate::getName) + .findFirst(); + String candidateName=name.get(); + Optional image = parentPost.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> candidate.getId().equals(id)) + .map(Candidate::getImage) + .findFirst(); + String candidateImage=image.get(); + parentPollDTO.setCandidateName(candidateName); + parentPollDTO.setCandidateImage(candidateImage); return ParentPostDTO.builder() .nickname(parentPost.getUser().getNickname()) @@ -133,6 +148,21 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ // 1등 후보의 정보를 ParentPollDTO 객체로 반환 parentPollDTO = highestSelectionCandidate.get(); + // 1등 후보 이름, 사진 반환 + Long id=parentPollDTO.getCandidateId(); + Optional name = parentPost.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> candidate.getId().equals(id)) + .map(Candidate::getName) + .findFirst(); + String candidateName=name.get(); + Optional image = parentPost.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> candidate.getId().equals(id)) + .map(Candidate::getImage) + .findFirst(); + String candidateImage=image.get(); + parentPollDTO.setCandidateName(candidateName); + parentPollDTO.setCandidateImage(candidateImage); + return ParentPostDTO.builder() .nickname(parentPost.getUser().getNickname()) diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 5a277bf..a0b5d92 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -210,6 +210,9 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque if(newPost.getPostType()==REVIEW&&request.getParent_id()!=null){ Post parent=postRepository.findById(request.getParent_id()) .orElseThrow(()->new RuntimeException("\""+request.getParent_id()+"\"해당 글이 없습니다")); + if(!userId.equals(parent.getUser().getId())){ + throw new RuntimeException("타 유저 글입니다. 후기글 작성 권한이 없습니다."); + } newPost.setParentPost(parent); } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 19ee9d6..eaf0aee 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -149,7 +149,7 @@ public ApiResponse editPost(@PathVariable("post-id") Long postId, } @PatchMapping("/{post-id}/del") - @Operation(summary = "댓글 삭제 API", description = "댓글 삭제하는 API입니다. ex) /posts/1/comment/1/del") + @Operation(summary = "글 삭제 API", description = "글 삭제하는 API입니다. ex) /posts/1/comment/1/del") @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), diff --git a/src/main/java/friend/spring/web/dto/ParentPollDTO.java b/src/main/java/friend/spring/web/dto/ParentPollDTO.java index eee0dd5..89f6bf4 100644 --- a/src/main/java/friend/spring/web/dto/ParentPollDTO.java +++ b/src/main/java/friend/spring/web/dto/ParentPollDTO.java @@ -8,6 +8,8 @@ @NoArgsConstructor @AllArgsConstructor public class ParentPollDTO{ + String candidateName; + String candidateImage; Long candidateId; Integer rate; Long selection; From aea3446b637b99c99f6737ce08d9af6737fa703f Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 7 Feb 2024 05:41:28 +0900 Subject: [PATCH 140/255] =?UTF-8?q?#83=20Feat:=20api=20endpoint=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD,=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=EC=8B=9C=20=ED=86=A0=ED=81=B0=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/web/controller/PostRestController.java | 2 +- .../spring/web/controller/UserRestController.java | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index eaf0aee..e8293b4 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -63,7 +63,7 @@ public ApiResponse join(@RequestBody @Valid Po } - @GetMapping("/voteList") + @GetMapping("/poll-postList") @Operation(summary = "후기글 작성시 내투표 보기 API", description = "후기글 작성시 내투표 보기합니다.") @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index df3e863..73e5223 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -9,11 +9,7 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.repository.UserRepository; -import friend.spring.service.CommentService; -import friend.spring.service.EmailService; -import friend.spring.service.PostService; -import friend.spring.service.UserService; -import friend.spring.service.UserServiceImpl; +import friend.spring.service.*; import friend.spring.web.dto.AlarmResponseDTO; import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; @@ -41,6 +37,8 @@ public class UserRestController { private final EmailService mailService; private final PostService postService; private final CommentService commentService; + private final JwtTokenService jwtTokenService; + //마이 페이지 조회 @GetMapping("/my-page") @@ -117,7 +115,10 @@ public ApiResponse logout(@RequestHeader(name = "atk") String atk, HttpS @GetMapping("/point") @Operation(summary = "포인트 조회 API", description = "임시로 user-id 입력") - public ApiResponse myPoint(@RequestHeader(name = "id") Long userId) { + public ApiResponse myPoint(@RequestHeader("atk") String atk, + HttpServletRequest request2) { + + Long userId=jwtTokenService.JwtToId(request2); Integer point = userService.pointCheck(userId); return ApiResponse.onSuccess(UserConverter.toPointViewResDTO(point)); } From 274f5b5883a956b0c1b8e770575fa68c45a1a9a4 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 8 Feb 2024 13:09:11 +0900 Subject: [PATCH 141/255] =?UTF-8?q?#86=20Refactor:=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EB=B0=A9=EC=8B=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20=EA=B8=B0=ED=83=80=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81(=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85,=20?= =?UTF-8?q?=ED=9B=84=EA=B8=B0=EA=B8=80=20=EC=9E=91=EC=84=B1=20=EC=8B=9C=20?= =?UTF-8?q?=EB=82=B4=20=ED=88=AC=ED=91=9C=20=EB=B3=B4=EA=B8=B0,=20?= =?UTF-8?q?=ED=9B=84=EB=B3=B4=20=EB=93=B1=EB=A1=9D)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nginx/conf.d/client_max_body_size.conf | 2 +- .../apiPayload/code/status/ErrorStatus.java | 4 +- .../friend/spring/aws/s3/AmazonS3Manager.java | 4 +- .../friend/spring/config/AmazonConfig.java | 5 +- .../spring/converter/CandidateConverter.java | 7 + .../spring/converter/CommentConverter.java | 8 +- .../spring/converter/FileConverter.java | 32 ++++ ...MultipartJackson2HttpMessageConverter.java | 31 ++++ .../spring/converter/PostConverter.java | 79 +++++----- .../spring/converter/UserConverter.java | 35 +++- .../java/friend/spring/domain/Candidate.java | 10 +- src/main/java/friend/spring/domain/File.java | 32 ++++ src/main/java/friend/spring/domain/Post.java | 7 +- src/main/java/friend/spring/domain/User.java | 8 +- .../spring/domain/enums/S3ImageType.java | 5 + .../spring/repository/FileRepository.java | 7 + .../friend/spring/service/PostService.java | 12 +- .../spring/service/PostServiceImpl.java | 149 +++++++++++++++--- .../java/friend/spring/service/S3Service.java | 44 +++++- .../spring/service/UserServiceImpl.java | 3 +- .../web/controller/PostRestController.java | 46 ++++-- .../spring/web/controller/S3Controller.java | 17 +- .../spring/web/dto/CandidateResponseDTO.java | 16 +- .../java/friend/spring/web/dto/FileDTO.java | 13 ++ .../friend/spring/web/dto/ParentPostDTO.java | 3 +- .../friend/spring/web/dto/PollOptionDTO.java | 30 +++- .../friend/spring/web/dto/PostRequestDTO.java | 5 +- .../spring/web/dto/PostResponseDTO.java | 16 +- .../friend/spring/web/dto/UserRequestDTO.java | 1 - src/main/resources/application.yml | 6 +- 30 files changed, 500 insertions(+), 137 deletions(-) create mode 100644 src/main/java/friend/spring/converter/FileConverter.java create mode 100644 src/main/java/friend/spring/converter/MultipartJackson2HttpMessageConverter.java create mode 100644 src/main/java/friend/spring/domain/File.java create mode 100644 src/main/java/friend/spring/domain/enums/S3ImageType.java create mode 100644 src/main/java/friend/spring/repository/FileRepository.java create mode 100644 src/main/java/friend/spring/web/dto/FileDTO.java diff --git a/.platform/nginx/conf.d/client_max_body_size.conf b/.platform/nginx/conf.d/client_max_body_size.conf index aaf16cc..8e8277e 100644 --- a/.platform/nginx/conf.d/client_max_body_size.conf +++ b/.platform/nginx/conf.d/client_max_body_size.conf @@ -1 +1 @@ -# client_max_body_size 200M; \ No newline at end of file +client_max_body_size 200M; \ No newline at end of file diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 0fa1400..f62e965 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -33,7 +33,8 @@ public enum ErrorStatus implements BaseErrorCode { POST_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "POST4002", "올바른 사용자(글 작성자)가 아닙니다."), POST_LIKE_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4003", "글에 대한 좋아요 데이터를 찾을 수 없습니다."), POST_SCRAP_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4004", "글에 대한 스크랩 데이터를 찾을 수 없습니다."), - COMMENT_LIKE_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4005", "글에 대한 좋아요 데이터가 이미 존재합니다."), + POST_GENERAL_POLL_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4005", "글에 대한 일반 투표 데이터를 찾을 수 없습니다."), + POST_CARD_POLL_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4006", "글에 대한 카드 투표 데이터를 찾을 수 없습니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), @@ -42,6 +43,7 @@ public enum ErrorStatus implements BaseErrorCode { COMMENT_SELECT_MYSELF(HttpStatus.BAD_REQUEST, "COMMENT4004", "자기 자신은 채택할 수 없습니다."), COMMENT_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "COMMENT4005", "올바른 사용자(댓글 작성자)가 아닙니다."), COMMENT_POST_NOT_MATCH(HttpStatus.BAD_REQUEST, "COMMENT4006", "해당 글에 작성된 댓글이 아닙니다."), + COMMENT_LIKE_DUPLICATE(HttpStatus.BAD_REQUEST, "COMMENT4007", "댓글에 대한 좋아요 데이터가 이미 존재합니다."), // 알림 관련 응답 ALARM_NOT_FOUND(HttpStatus.NOT_FOUND, "ALARM4001", "알림이 없습니다"), diff --git a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java index 1c32fe3..5046e3c 100644 --- a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java +++ b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java @@ -55,7 +55,7 @@ public String generatePostKeyName(Uuid uuid) { return amazonConfig.getPostPath() + '/' + uuid.getUuid(); } - public String generateReportKeyName(Uuid uuid) { - return amazonConfig.getReportPath() + '/' + uuid.getUuid(); + public String generateCandidateKeyName(Uuid uuid) { + return amazonConfig.getCandidatePath() + '/' + uuid.getUuid(); } } \ No newline at end of file diff --git a/src/main/java/friend/spring/config/AmazonConfig.java b/src/main/java/friend/spring/config/AmazonConfig.java index a0597eb..0e90f23 100644 --- a/src/main/java/friend/spring/config/AmazonConfig.java +++ b/src/main/java/friend/spring/config/AmazonConfig.java @@ -38,8 +38,9 @@ public class AmazonConfig { @Value("${cloud.aws.s3.path.post}") private String postPath; - @Value("${cloud.aws.s3.path.report}") - private String reportPath; + @Value("${cloud.aws.s3.path.candidate}") + private String candidatePath; + @PostConstruct public void init() { diff --git a/src/main/java/friend/spring/converter/CandidateConverter.java b/src/main/java/friend/spring/converter/CandidateConverter.java index 589ad6b..666b38f 100644 --- a/src/main/java/friend/spring/converter/CandidateConverter.java +++ b/src/main/java/friend/spring/converter/CandidateConverter.java @@ -12,4 +12,11 @@ public static CandidateResponseDTO.CandidateSummaryRes toCandidateSummaryRes(Can .ratio(percent) .build(); } + + public static CandidateResponseDTO.AddCandidateResultDTO toAddCandidateResultDTO(Candidate candidate) { + return CandidateResponseDTO.AddCandidateResultDTO.builder() + .candidateId(candidate.getId()) + .createdAt(candidate.getCreatedAt()) + .build(); + } } diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index efef77e..4593655 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -53,12 +53,18 @@ public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment) } } + // 유저 프로필 + String userPhoto = null; + if (comment.getUser().getFile() != null) { + userPhoto = comment.getUser().getFile().getUrl(); + } + return CommentResponseDTO.commentGetRes.builder() .commentId(comment.getId()) .content(comment.getContent()) .userId(comment.getUser().getId()) .userNickname(comment.getUser().getNickname()) - .userImage(comment.getUser().getImage()) + .userImage(userPhoto) .createdAt(comment.getCreatedAt()) .updatedAt(comment.getUpdatedAt()) .parentCommentId(parentCommentId) diff --git a/src/main/java/friend/spring/converter/FileConverter.java b/src/main/java/friend/spring/converter/FileConverter.java new file mode 100644 index 0000000..dba886a --- /dev/null +++ b/src/main/java/friend/spring/converter/FileConverter.java @@ -0,0 +1,32 @@ +package friend.spring.converter; + +import friend.spring.domain.Candidate; +import friend.spring.domain.File; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.web.dto.FileDTO; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class FileConverter { + + public static File toFile(String pictureUrl, User user, Post post, Candidate candidate) { + return File.builder() + .url(pictureUrl) + .user(user) + .post(post) + .candidate(candidate) + .build(); + } + + public static List toFileDTO(List fileList) { + return fileList.stream() + .map(file -> FileDTO.builder() + .imageId(file.getId()) + .imageUrl(file.getUrl()) + .build()) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/friend/spring/converter/MultipartJackson2HttpMessageConverter.java b/src/main/java/friend/spring/converter/MultipartJackson2HttpMessageConverter.java new file mode 100644 index 0000000..983139a --- /dev/null +++ b/src/main/java/friend/spring/converter/MultipartJackson2HttpMessageConverter.java @@ -0,0 +1,31 @@ +package friend.spring.converter; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Type; + +@Component +public class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter { + + public MultipartJackson2HttpMessageConverter(ObjectMapper objectMapper) { + super(objectMapper, MediaType.APPLICATION_OCTET_STREAM); + } + + @Override + public boolean canWrite(Class clazz, MediaType mediaType) { + return false; + } + + @Override + public boolean canWrite(Type type, Class clazz, MediaType mediaType) { + return false; + } + + @Override + protected boolean canWrite(MediaType mediaType) { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 7a1db2e..128abaf 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -3,8 +3,6 @@ import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; -import friend.spring.repository.CandidateRepository; -import friend.spring.security.JwtTokenProvider; import friend.spring.service.PostQueryService; import friend.spring.web.dto.*; import org.springframework.data.domain.Page; @@ -36,10 +34,14 @@ public static PostResponseDTO.AddPostResultDTO toAddPostResultDTO(Post post) { .build(); } - public static PollOptionDTO toPollOptionDTO(Candidate candidate){ - return PollOptionDTO.builder() + public static PollOptionDTO.PollOptionRes toPollOptionResDTO(Candidate candidate) { + String optionImgUrl = null; + if (candidate.getFile() != null) { + optionImgUrl = candidate.getFile().getUrl(); + } + return PollOptionDTO.PollOptionRes.builder() .optionString(candidate.getName()) - .optionImg(candidate.getImage()).build(); + .optionImgUrl(optionImgUrl).build(); } public static ParentPostDTO toParentPostDTO(Post parentPost){ @@ -59,8 +61,8 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ } if(parentPost.getVoteType()==PostVoteType.GENERAL) { - List pollOptionDTOList = parentPost.getGeneralPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + List pollOptionDTOList = parentPost.getGeneralPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); // 총 투표수 계산 long totalVotes = parentPost.getGeneralPoll().getGeneralVoteList().stream() @@ -97,11 +99,11 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ .map(Candidate::getName) .findFirst(); String candidateName=name.get(); - Optional image = parentPost.getGeneralPoll().getCandidateList().stream() + Optional image = parentPost.getGeneralPoll().getCandidateList().stream() .filter(candidate -> candidate.getId().equals(id)) - .map(Candidate::getImage) + .map(Candidate::getFile) .findFirst(); - String candidateImage=image.get(); + String candidateImage=image.get().getUrl(); parentPollDTO.setCandidateName(candidateName); parentPollDTO.setCandidateImage(candidateImage); @@ -116,8 +118,8 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ .build(); } - List pollOptionDTOList = parentPost.getCardPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + List pollOptionDTOList = parentPost.getCardPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); // 총 투표수 계산 long totalVotes = parentPost.getCardPoll().getCardVoteList().stream() @@ -152,11 +154,11 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ .map(Candidate::getName) .findFirst(); String candidateName=name.get(); - Optional image = parentPost.getGeneralPoll().getCandidateList().stream() + Optional image = parentPost.getGeneralPoll().getCandidateList().stream() .filter(candidate -> candidate.getId().equals(id)) - .map(Candidate::getImage) + .map(Candidate::getFile) .findFirst(); - String candidateImage=image.get(); + String candidateImage=image.get().getUrl(); parentPollDTO.setCandidateName(candidateName); parentPollDTO.setCandidateImage(candidateImage); @@ -204,10 +206,11 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { } } + + return Post.builder() .title(request.getTitle()) .content(request.getContent()) - .file(request.getFile()) .postType(postType) .voteType(postVoteType) .point(request.getPoint()) @@ -223,7 +226,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); Boolean myPost=false; - List userChoiceList=null; + List userChoiceList=null; List percent=null; List voteResult=null; Integer value=null; @@ -240,7 +243,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .file(post.getFile()) + .file(FileConverter.toFileDTO(post.getFileList())) .parentPost(toParentPostDTO(parentPost)) .view(post.getView()) .like(likeCount) @@ -259,7 +262,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .file(post.getFile()) + .file(FileConverter.toFileDTO(post.getFileList())) .gauge(value) .point(post.getPoint()) .deadline(post.getGaugePoll().getDeadline()) @@ -272,8 +275,8 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .build(); } if(post.getVoteType()==PostVoteType.GENERAL){ - List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); if(engage) { //투표한 후보에 대한 정보 Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() @@ -282,7 +285,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .collect(Collectors.toSet()); userChoiceList = post.getGeneralPoll().getCandidateList().stream() .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionDTO) + .map(PostConverter::toPollOptionResDTO) .collect(Collectors.toList()); // 총 투표수 계산 @@ -323,7 +326,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .file(post.getFile()) + .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getGeneralPoll().getPollTitle()) .pollOption(pollOptionDTOList) .point(post.getPoint()) @@ -339,8 +342,8 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .myPost(myPost) .build(); } - List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); if(engage) { //투표한 후보에 대한 정보 Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() @@ -349,7 +352,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .collect(Collectors.toSet()); userChoiceList = post.getCardPoll().getCandidateList().stream() .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionDTO) + .map(PostConverter::toPollOptionResDTO) .collect(Collectors.toList()); // 총 투표수 계산 @@ -390,7 +393,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .file(post.getFile()) + .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getCardPoll().getPollTitle()) .pollOption(pollOptionDTOList) .point(post.getPoint()) @@ -419,14 +422,14 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); - List userChoiceList=null; + List userChoiceList=null; Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); Boolean engage=false; if(post.getVoteType()==PostVoteType.GENERAL) { - List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); if(!post.getGeneralPoll().getGeneralVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()){ engage=true; } @@ -438,7 +441,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .collect(Collectors.toSet()); userChoiceList = post.getGeneralPoll().getCandidateList().stream() .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionDTO) + .map(PostConverter::toPollOptionResDTO) .collect(Collectors.toList()); return PostResponseDTO.PollPostGetResponse.builder() @@ -495,8 +498,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .isComment(isComment) .build(); } - List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionDTO).collect(Collectors.toList()); + List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); System.out.println("fuck"); if(!post.getCardPoll().getCardVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()){ engage=true; @@ -509,7 +512,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .collect(Collectors.toSet()); userChoiceList = post.getCardPoll().getCandidateList().stream() .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionDTO) + .map(PostConverter::toPollOptionResDTO) .collect(Collectors.toList()); return PostResponseDTO.PollPostGetResponse.builder() @@ -557,16 +560,13 @@ public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post p .nickname(post.getUser().getNickname()) .title(post.getTitle()) .content(post.getContent()) - .ReviewPic(post.getFile()) + .ReviewPicList(FileConverter.toFileDTO(post.getFileList())) .uploadDate(post.getCreatedAt()) .like(likeCount) .comment(commentCount) .isLike(isLike) .isComment(isComment) .build(); - - - } public static PostResponseDTO.ReviewPostGetListDTO reviewPostGetListDTO(Page postList,Long userId){ @@ -582,6 +582,7 @@ public static ParentPostDTO.CandidatePostDTO candidatePostDTO(Post post){ Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); return ParentPostDTO.CandidatePostDTO.builder() + .postId(post.getId()) .title(post.getTitle()) .content(post.getContent()) .like(likeCount) @@ -630,7 +631,7 @@ public static PostResponseDTO.PostSummaryListRes toPostSummaryRes(Post post, Int .title(post.getTitle()) .content(post.getContent()) .post_id(post.getId()) - .file(post.getFile()) + .file(FileConverter.toFileDTO(post.getFileList())) .like(like_cnt) .comment_cnt(comment_cnt) .created_at(post.getCreatedAt()) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index e7fede3..a36192b 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -21,8 +21,13 @@ public class UserConverter { public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ + String userPhoto = null; + if (user.getFile() != null) { + userPhoto = user.getFile().getUrl(); + } + return UserResponseDTO.MyPageResDTO.builder() - .userPhoto(user.getImage()) + .userPhoto(userPhoto) .userName(user.getNickname()) .userPoint(user.getPoint()) .userLevelInt(user.getLevel().getLike()+1) @@ -55,7 +60,7 @@ public static UserResponseDTO.JoinResultDTO joinResultDTO(User user){ } - public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest, String pw){ + public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest, String pw, Level initLevel){ Gender gender = null; @@ -82,11 +87,11 @@ public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest, String .agree_marketing(userJoinRequest.isAgree_marketing()) .birth(userJoinRequest.getBirth()) .kakao(userJoinRequest.getKakao()) - .image(userJoinRequest.getImage()) .is_deleted(userJoinRequest.is_deleted()) .point(userJoinRequest.getPoint()) .like(userJoinRequest.getLike()) .role(RoleType.USER) + .level(initLevel) .build(); } @@ -114,10 +119,16 @@ public static UserResponseDTO.QuestionResDTO toQuestionResDTO(User user, Level n .filter(post -> post.getCommentChoiceList().isEmpty()).collect(Collectors.toList()); double pChoicePercent = ((double) (Question - myPostList.size()) / (double) Question)*100; + // 유저 프로필 + String userPhoto = null; + if (user.getFile() != null) { + userPhoto = user.getFile().getUrl(); + } + //남은 다음 등급 double nxtGrade = ((double)user.getLike()/(double)(nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; return UserResponseDTO.QuestionResDTO.builder() - .userPhoto(user.getImage()) + .userPhoto(userPhoto) .nickName(user.getNickname()) .recommend(user.getLike()) .grade(user.getLevel().getName()) @@ -146,10 +157,16 @@ public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLe //채택 답변률 double percent = ((double)choice / (double)all) * 100.0; + // 유저 프로필 + String userPhoto = null; + if (user.getFile() != null) { + userPhoto = user.getFile().getUrl(); + } + //남은 다음 등급 double nxtGrade = ((double)user.getLike()/(double)(nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; return UserResponseDTO.AnswerResDTO.builder() - .userPhoto(user.getImage()) + .userPhoto(userPhoto) .nickName(user.getNickname()) .recommend(user.getLike()) .grade(user.getLevel().getName()) @@ -162,10 +179,16 @@ public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLe } public static UserResponseDTO.UserSummaryInfo toUserSummaryInfo(User user) { + // 유저 프로필 + String userPhoto = null; + if (user.getFile() != null) { + userPhoto = user.getFile().getUrl(); + } + return UserResponseDTO.UserSummaryInfo.builder() .user_id(user.getId()) .nickname(user.getNickname()) - .image(user.getImage()) + .image(userPhoto) .build(); } diff --git a/src/main/java/friend/spring/domain/Candidate.java b/src/main/java/friend/spring/domain/Candidate.java index 8617efb..df28ea8 100644 --- a/src/main/java/friend/spring/domain/Candidate.java +++ b/src/main/java/friend/spring/domain/Candidate.java @@ -18,8 +18,6 @@ public class Candidate extends BaseEntity { private String name; - private String image; - @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "generalPoll_id") private General_poll generalPoll; @@ -28,6 +26,10 @@ public class Candidate extends BaseEntity { @JoinColumn(name = "cardPoll_id") private Card_poll cardPoll; + @OneToOne(mappedBy = "candidate") + @JoinColumn(name = "file_id") + private File file; + public void setGeneralPoll(General_poll generalPoll) { this.generalPoll = generalPoll; if (this.generalPoll != null) { @@ -48,5 +50,7 @@ public void setCardPoll(Card_poll cardPoll) { } } - + public void setFile(File file) { + this.file = file; + } } diff --git a/src/main/java/friend/spring/domain/File.java b/src/main/java/friend/spring/domain/File.java new file mode 100644 index 0000000..6e7cdc2 --- /dev/null +++ b/src/main/java/friend/spring/domain/File.java @@ -0,0 +1,32 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import lombok.*; + +import javax.persistence.*; + +@Entity +@Builder +@Getter +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class File extends BaseEntity { // S3에 저장한 이미지 파일 링크들 관리 + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(unique = true) + private String url; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "post_id") + private Post post; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "candidate_id") + private Candidate candidate; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; +} diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 44c17d3..f07bb4d 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -50,8 +50,8 @@ public class Post extends BaseEntity { @Column(nullable = true) private Integer point; - @Column(nullable = true) - private String file; +// @Column(nullable = true) +// private String file; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") @@ -92,6 +92,9 @@ public class Post extends BaseEntity { @OneToMany(mappedBy = "post") private List commentChoiceList = new ArrayList<>(); + @Builder.Default + @OneToMany(mappedBy = "post") + private List fileList = new ArrayList<>(); @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "cardPoll_id") diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 701beda..731637f 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -58,8 +58,8 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true) private Boolean agree_info; - @Column(nullable = true) - private String image; +// @Column(nullable = true) +// private String image; @Column(nullable = true)//잠시 true로 수정 private Boolean is_deleted; @@ -122,6 +122,10 @@ public class User extends BaseEntity implements UserDetails { @OneToMany(mappedBy = "user") private List gaugeVoteList = new ArrayList<>(); + @OneToOne(mappedBy = "user") + @JoinColumn(name = "file_id") + private File file; + // UserDetails 상속 @Override public Collection getAuthorities() { diff --git a/src/main/java/friend/spring/domain/enums/S3ImageType.java b/src/main/java/friend/spring/domain/enums/S3ImageType.java new file mode 100644 index 0000000..5e6af23 --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/S3ImageType.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum S3ImageType { + USER, POST, CANDIDATE +} diff --git a/src/main/java/friend/spring/repository/FileRepository.java b/src/main/java/friend/spring/repository/FileRepository.java new file mode 100644 index 0000000..9544859 --- /dev/null +++ b/src/main/java/friend/spring/repository/FileRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.File; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FileRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index f9b4424..37522f3 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -1,13 +1,18 @@ package friend.spring.service; +import friend.spring.domain.Candidate; import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; +import friend.spring.web.dto.PollOptionDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.util.List; @@ -20,7 +25,11 @@ public interface PostService { void checkPostLike(Boolean flag); - Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2); + Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2, List file); + +// Candidate createCandidate(Long postId, PollOptionDTO.PollOptionReq request, HttpServletRequest request2); + + Candidate createCandidate(Long postId, String optionString, MultipartFile optionImg, HttpServletRequest request2); Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user); @@ -46,6 +55,5 @@ public interface PostService { Post_scrap createScrapPost(Long postId, HttpServletRequest request); void deleteScrapPost(Long postId, HttpServletRequest request); - } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index f93b092..0737140 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -7,6 +7,7 @@ import friend.spring.converter.CandidateConverter; import friend.spring.converter.PostConverter; import friend.spring.domain.*; +import friend.spring.domain.enums.S3ImageType; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; import friend.spring.repository.*; @@ -19,6 +20,8 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; import java.util.Objects; @@ -51,6 +54,8 @@ public class PostServiceImpl implements PostService{ private final UserService userService; private final JwtTokenProvider jwtTokenProvider; + private final S3Service s3Service; + @Override public void checkPost(Boolean flag) { if (!flag) { @@ -89,20 +94,35 @@ public void checkPostScrap(Boolean flag) { @Override @Transactional - public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2) { + public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2, List file) { + System.out.println("테스트0"); Long userId = jwtTokenProvider.getCurrentUser(request2); + + System.out.println("테스트0.5"); + Post newPost= PostConverter.toPost(request); + System.out.println("테스트0.7"); User user=userRepository.findById(userId) .orElseThrow(()->new RuntimeException("\""+userId+"\"해당 유저가 없습니다")); + System.out.println("테스트0.9"); newPost.setUser(user); + System.out.println("테스트1"); + + // 글 첨부파일 사진 저장 + s3Service.uploadPostImages(file, S3ImageType.POST, newPost); + + System.out.println("테스트2"); + //일반 투표 api if(newPost.getPostType()==VOTE){ newPost.setCategory(categoryRepository.findByName(request.getCategory())); } - if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL&&request.getPollOption()!=null){ + System.out.println("테스트3"); +// if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL&&pollOption!=null){ + if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL){ //포인트 차감 관련 코드 if(request.getPoint()!=null) { if (!checkPoint(request, user)) { @@ -116,6 +136,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque newPoint.setUser(user); pointRepository.save(newPoint); } + System.out.println("테스트4"); General_poll generalPoll = General_poll.builder() .pollTitle(request.getPollTitle()) @@ -125,21 +146,27 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque generalPoll.setMultipleChoice(request.getMultipleChoice()); } newPost.setGeneralPoll(generalPoll); + System.out.println("테스트5"); generalPollRepository.save(generalPoll); - - for (PollOptionDTO option : request.getPollOption()) { - Candidate candidate = Candidate.builder() - .name(option.getOptionString()) - .image(option.getOptionImg()) - .build(); - - candidate.setGeneralPoll(generalPoll); - candidateRepository.save(candidate); - } + System.out.println("테스트6"); + +// for (PollOptionDTO.PollOptionReq option : pollOption) { +// Candidate candidate = Candidate.builder() +// .name(option.getOptionString()) +// .build(); +// +// File candidateFile = s3Service.uploadSingleImage(option.getOptionImg(), S3ImageType.CANDIDATE, null, candidate); +// candidate.setFile(candidateFile); +// +// candidate.setGeneralPoll(generalPoll); +// candidateRepository.save(candidate); +// } + System.out.println("테스트7"); } //카드 투표 api - if(newPost.getPostType()==VOTE&&newPost.getVoteType()==CARD&&request.getPollOption()!=null){ +// if(newPost.getPostType()==VOTE&&newPost.getVoteType()==CARD&&pollOption!=null){ + if(newPost.getPostType()==VOTE&&newPost.getVoteType()==CARD){ //포인트 차감 관련 코드 if(request.getPoint()!=null) { if (!checkPoint(request, user)) { @@ -153,6 +180,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque newPoint.setUser(user); pointRepository.save(newPoint); } + System.out.println("테스트8"); if(!checkPoint(request, user)&&request.getPoint()!=null){ throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); @@ -167,16 +195,20 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque } newPost.setCardPoll(cardPoll); cardPollRepository.save(cardPoll); - - for (PollOptionDTO option : request.getPollOption()) { - Candidate candidate = Candidate.builder() - .name(option.getOptionString()) - .image(option.getOptionImg()) - .build(); - - candidate.setCardPoll(cardPoll); - candidateRepository.save(candidate); - } + System.out.println("테스트9"); + +// for (PollOptionDTO.PollOptionReq option : pollOption) { +// Candidate candidate = Candidate.builder() +// .name(option.getOptionString()) +// .build(); +// +// File candidateFile = s3Service.uploadSingleImage(option.getOptionImg(), S3ImageType.CANDIDATE, null, candidate); +// candidate.setFile(candidateFile); +// +// candidate.setCardPoll(cardPoll); +// candidateRepository.save(candidate); +// } + System.out.println("테스트10"); } //게이지 투표 api if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GAUGE){ @@ -217,10 +249,78 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque newPost.setParentPost(parent); } + System.out.println("테스트11"); return postRepository.save(newPost); } +// @Override +// public Candidate createCandidate(Long postId, PollOptionDTO.PollOptionReq request, HttpServletRequest request2) { +// Post newPost = postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); +// +// Long userId = jwtTokenProvider.getCurrentUser(request2); +// User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); +// if (!newPost.getUser().equals(user)) { // 이 글을 쓴 사용자인지 검증 +// this.checkPostWriterUser(false); +// } +// +// Candidate candidate = Candidate.builder() +// .name(request.getOptionString()) +// .build(); +// +// File candidateFile = s3Service.uploadSingleImage(request.getOptionImg(), S3ImageType.CANDIDATE, null, candidate); +// candidate.setFile(candidateFile); +// +// // 일반 투표 +// if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL) { +// General_poll generalPoll = generalPollRepository.findById(newPost.getGeneralPoll().getId()).orElseThrow(() -> new GeneralException(POST_GENERAL_POLL_NOT_FOUND)); +// candidate.setGeneralPoll(generalPoll); +// } +// // 카드 투표 +// else { +// Card_poll cardPoll = cardPollRepository.findById(newPost.getCardPoll().getId()).orElseThrow(() -> new GeneralException(POST_CARD_POLL_NOT_FOUND)); +// candidate.setCardPoll(cardPoll); +// } +// +// return candidateRepository.save(candidate); +// } + + @Override + @Transactional + public Candidate createCandidate(Long postId, String optionString, MultipartFile optionImg, HttpServletRequest request2) { + Post newPost = postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); + + Long userId = jwtTokenProvider.getCurrentUser(request2); + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); + if (!newPost.getUser().equals(user)) { // 이 글을 쓴 사용자인지 검증 + this.checkPostWriterUser(false); + } + + Candidate candidate = Candidate.builder() + .name(optionString) + .build(); + + candidateRepository.save(candidate); + + if (optionImg != null) { + File candidateFile = s3Service.uploadSingleImage(optionImg, S3ImageType.CANDIDATE, null, candidate); + candidate.setFile(candidateFile); + } + + // 일반 투표 + if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL) { + General_poll generalPoll = generalPollRepository.findById(newPost.getGeneralPoll().getId()).orElseThrow(() -> new GeneralException(POST_GENERAL_POLL_NOT_FOUND)); + candidate.setGeneralPoll(generalPoll); + } + // 카드 투표 + else { + Card_poll cardPoll = cardPollRepository.findById(newPost.getCardPoll().getId()).orElseThrow(() -> new GeneralException(POST_CARD_POLL_NOT_FOUND)); + candidate.setCardPoll(cardPoll); + } + + return candidate; + } + @Override @Transactional public void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId){ @@ -332,6 +432,9 @@ public List getPostRes(Page postPage) Long card_poll_id = null; List candidateList = null; List candidateSummaryResList = null; + + if (post.getVoteType() == null) return null; // 고민 후기 글인 경우 패스 + if (post.getVoteType().equals(GENERAL)) { // 일반 투표인 경우 postVoteType = "GENERAL"; general_poll_id = post.getGeneralPoll().getId(); diff --git a/src/main/java/friend/spring/service/S3Service.java b/src/main/java/friend/spring/service/S3Service.java index 2c34a8f..d24c34b 100644 --- a/src/main/java/friend/spring/service/S3Service.java +++ b/src/main/java/friend/spring/service/S3Service.java @@ -1,13 +1,18 @@ package friend.spring.service; import friend.spring.aws.s3.AmazonS3Manager; -import friend.spring.domain.Uuid; +import friend.spring.converter.FileConverter; +import friend.spring.domain.*; +import friend.spring.domain.enums.S3ImageType; +import friend.spring.repository.FileRepository; import friend.spring.repository.UuidRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; @Service @@ -17,13 +22,36 @@ public class S3Service { private final UuidRepository uuidRepository; private final AmazonS3Manager s3Manager; - // 유저 프로필 사진 올리기인 경우 - public String uploadUserImage(MultipartFile file) { - String uuid = UUID.randomUUID().toString(); - Uuid savedUuid = uuidRepository.save(Uuid.builder() - .uuid(uuid).build()); + private final FileRepository fileRepository; + + public List uploadPostImages(List multipartFiles, S3ImageType type, Post post) { + List fileList = new ArrayList<>(); + // forEach 구문을 통해 multipartFiles 리스트로 넘어온 파일들을 순차적으로 fileNameList 에 추가 + multipartFiles.forEach(file -> { + String pictureUrl = s3Manager.uploadFile(s3Manager.generatePostKeyName(createFileName()), file); + File newFile = fileRepository.save(FileConverter.toFile(pictureUrl, null, post, null)); + fileList.add(newFile); + }); + return fileList; + } + + public File uploadSingleImage(MultipartFile file, S3ImageType type, User user, Candidate candidate) { + File newFile; + if (type == S3ImageType.USER && user != null) { // 사용자 프로필 이미지인 경우 + String pictureUrl = s3Manager.uploadFile(s3Manager.generateUserKeyName(createFileName()), file); + newFile = fileRepository.save(FileConverter.toFile(pictureUrl, user, null, null)); - String pictureUrl = s3Manager.uploadFile(s3Manager.generateUserKeyName(savedUuid), file); - return pictureUrl; + } else { // 후보 이미지인 경우 + String pictureUrl = s3Manager.uploadFile(s3Manager.generateCandidateKeyName(createFileName()), file); + newFile = fileRepository.save(FileConverter.toFile(pictureUrl, null, null, candidate)); + } + return newFile; + } + + + // 먼저 파일 업로드시, 파일명을 난수화하기 위해 UUID 를 활용하여 난수를 돌린다. + public Uuid createFileName() { + String uuid = UUID.randomUUID().toString(); + return uuidRepository.save(Uuid.builder().uuid(uuid).build()); } } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 01e97a9..88e5218 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -67,7 +67,8 @@ public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest) {//회원 String encodedPw = encoder.encode(userJoinRequest.getPassword()); - User newUser = UserConverter.toUser(userJoinRequest, encodedPw); + Level initLevel = levelRepository.findById(Long.valueOf(1)).get(); + User newUser = UserConverter.toUser(userJoinRequest, encodedPw, initLevel); return userRepository.saveAndFlush(newUser); } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 22dccab..48e26ed 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -1,32 +1,32 @@ package friend.spring.web.controller; import friend.spring.apiPayload.ApiResponse; -import friend.spring.converter.CommentConverter; +import friend.spring.converter.CandidateConverter; import friend.spring.converter.PostConverter; +import friend.spring.domain.Candidate; import friend.spring.domain.Post; import friend.spring.repository.PostRepository; import friend.spring.service.JwtTokenService; import friend.spring.service.PostQueryService; import friend.spring.service.PostService; -import friend.spring.web.dto.ParentPostDTO; -import friend.spring.domain.mapping.Comment_like; +import friend.spring.web.dto.*; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; -import friend.spring.service.PostService; -import friend.spring.web.dto.CommentResponseDTO; -import friend.spring.web.dto.PostRequestDTO; -import friend.spring.web.dto.PostResponseDTO; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; -import org.springframework.http.ResponseEntity; +import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; +import java.util.List; import java.util.Optional; @RestController @@ -38,7 +38,8 @@ public class PostRestController { private final PostQueryService postQueryService; private final PostRepository postRepository; private final JwtTokenService jwtTokenService; - @PostMapping("/") +// @PostMapping(value = "/", consumes = "multipart/form-data") + @PostMapping(value = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @Operation(summary = "글 작성 API", description = "글을 추가 합니다.") @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @@ -49,19 +50,40 @@ public class PostRestController { @Parameter(name="postVoteType", description=" 투표 종류
1 : GENERAL
2 : GAUGE
3 : CARD
해당 사항 없을시 null"), @Parameter(name="pollTitle", description=" 투표 제목"), @Parameter(name="multipleChoice", description=" 복수 선택 여부"), - @Parameter(name="pollOption", description=" 투표 후보{optionString : string, optionImg : string}
해당 사항 없을시 null"), +// @Parameter(name="pollOption", description=" 투표 후보{optionString : string, optionImg : string}
해당 사항 없을시 null"), @Parameter(name="parent_id", description=" 원글(후기글 경우) id
해당 사항 없을시 null"), @Parameter(name="deadline", description=" 투표 마감 시간
해당 사항 없을시 null"), @Parameter(name="point", description=" 포인트
해당 사항 없을시 null") }) - public ApiResponse join(@RequestBody @Valid PostRequestDTO.AddPostDTO request, + public ApiResponse join(@RequestPart(value = "request") @Valid PostRequestDTO.AddPostDTO request, + @RequestPart(value = "file", required = false) List file, +// @RequestPart(value = "pollOptionImages", required = false) List pollOptionFiles, @RequestHeader("atk") String atk, HttpServletRequest request2){ - Post post= postService.joinPost(request,request2); + System.out.println("테스트000000"); + Post post= postService.joinPost(request,request2, file); return ApiResponse.onSuccess(PostConverter.toAddPostResultDTO(post)); } + @PostMapping(value = "/{post-id}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @Operation(summary = "후보 생성 API", description = "후보를 생성합니다.(글 작성 API 호출 후 postId 응답 받으시면, 후보 개수 만큼 바로 호출해주세요!)") + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + @Parameter(name="pollOption", description=" 투표 후보{optionString : string, optionImg : MultipartFile}
해당 사항 없을시 null"), + }) + public ApiResponse createCandidate( + @PathVariable(name="post-id") Long postId, +// @RequestBody PollOptionDTO.PollOptionReq request, + @RequestParam String optionString, + @RequestParam(required = false) MultipartFile optionImg, + @RequestHeader("atk") String atk, + HttpServletRequest request2) { +// Candidate candidate = postService.createCandidate(postId, request,request2); + Candidate candidate = postService.createCandidate(postId, optionString, optionImg,request2); + return ApiResponse.onSuccess(CandidateConverter.toAddCandidateResultDTO(candidate)); + } + @GetMapping("/poll-postList") @Operation(summary = "후기글 작성시 내투표 보기 API", description = "후기글 작성시 내투표 보기합니다.") diff --git a/src/main/java/friend/spring/web/controller/S3Controller.java b/src/main/java/friend/spring/web/controller/S3Controller.java index 8052453..e9f9982 100644 --- a/src/main/java/friend/spring/web/controller/S3Controller.java +++ b/src/main/java/friend/spring/web/controller/S3Controller.java @@ -1,21 +1,24 @@ package friend.spring.web.controller; import friend.spring.apiPayload.ApiResponse; +import friend.spring.domain.enums.S3ImageType; import friend.spring.service.S3Service; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.util.List; + @RestController @RequiredArgsConstructor -@RequestMapping("/uploadImage") +@RequestMapping("/file") public class S3Controller { private final S3Service s3Service; - // 유저 이미지 올리기 - @PostMapping(value = "", consumes = "multipart/form-data") - public ApiResponse uploadUserImage(@RequestParam("file") MultipartFile file) { - String url = s3Service.uploadUserImage(file); - return ApiResponse.onSuccess(url); - } + // 유저 프로필 이미지 올리기 +// @PostMapping(value = "/uploadImage", consumes = "multipart/form-data") +// public ApiResponse> uploadUserImage(@RequestParam("file") List file) { +// List url = s3Service.uploadImage(file, S3ImageType.USER); +// return ApiResponse.onSuccess(url); +// } } diff --git a/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java b/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java index 6e6b64b..13b52a2 100644 --- a/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java @@ -1,9 +1,8 @@ package friend.spring.web.dto; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; + +import java.time.LocalDateTime; public class CandidateResponseDTO { @Builder @@ -15,4 +14,13 @@ public static class CandidateSummaryRes { String candidate_name; // 후보 이름 Double ratio; // 비율 } + + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class AddCandidateResultDTO { + Long candidateId; + LocalDateTime createdAt; + } } diff --git a/src/main/java/friend/spring/web/dto/FileDTO.java b/src/main/java/friend/spring/web/dto/FileDTO.java new file mode 100644 index 0000000..16ed195 --- /dev/null +++ b/src/main/java/friend/spring/web/dto/FileDTO.java @@ -0,0 +1,13 @@ +package friend.spring.web.dto; + +import lombok.*; + +@Getter +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class FileDTO { + private Long imageId; + private String imageUrl; +} diff --git a/src/main/java/friend/spring/web/dto/ParentPostDTO.java b/src/main/java/friend/spring/web/dto/ParentPostDTO.java index d0e8467..67f621b 100644 --- a/src/main/java/friend/spring/web/dto/ParentPostDTO.java +++ b/src/main/java/friend/spring/web/dto/ParentPostDTO.java @@ -14,7 +14,7 @@ public class ParentPostDTO { String nickname; String title; String content; - List pollOption; + List pollOption; ParentPollDTO pollContent; Integer gauge; Integer like; @@ -25,6 +25,7 @@ public class ParentPostDTO { @NoArgsConstructor @AllArgsConstructor public static class CandidatePostDTO { + Long postId; String title; String content; Integer like; diff --git a/src/main/java/friend/spring/web/dto/PollOptionDTO.java b/src/main/java/friend/spring/web/dto/PollOptionDTO.java index 06b0e24..379e1fc 100644 --- a/src/main/java/friend/spring/web/dto/PollOptionDTO.java +++ b/src/main/java/friend/spring/web/dto/PollOptionDTO.java @@ -1,13 +1,29 @@ package friend.spring.web.dto; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.*; +import org.springframework.web.multipart.MultipartFile; -@Getter -@Builder -@Data -@NoArgsConstructor -@AllArgsConstructor public class PollOptionDTO { - private String optionString; - private String optionImg; + + @Getter + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class PollOptionReq { + private String optionString; + private MultipartFile optionImg; + } + + @Getter + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class PollOptionRes { + private String optionString; + private String optionImgUrl; + } } diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index 42dbd66..7a4bc3d 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -8,6 +8,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import org.apache.tomcat.jni.Poll; +import org.springframework.web.multipart.MultipartFile; import javax.validation.constraints.NotBlank; import java.sql.Timestamp; @@ -26,12 +27,12 @@ public static class AddPostDTO{ Integer postVoteType;// 1: general, 2: gauge String pollTitle; Boolean multipleChoice; - List pollOption; +// List pollOption; Long parent_id; @NotBlank Timestamp deadline; Integer point; - String file; +// List file; } @Getter public static class ReviewPostGetDTO{ diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index fdc6f56..c95cfa4 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -1,12 +1,10 @@ package friend.spring.web.dto; -import friend.spring.domain.Candidate; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.*; -import java.sql.Time; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.List; @@ -30,14 +28,14 @@ public static class PostDetailResponse { LocalDateTime createdAt; String title; String content; - String file; + List file; // 첨부파일 이미지 리스트 String pollTitle; // 투표글에서만 사용, 후기글에서는 null - List pollOption; // 투표글에서만 사용, 후기글에서는 null + List pollOption; // 투표글에서만 사용, 후기글에서는 null Integer gauge; // 게이지 투표글에서만 사용, 후기글에서는 null Integer point; // 투표글에서만 사용, 후기글에서는 null ParentPostDTO parentPost; // 후기글에서만 사용, 일반글에서는 null Timestamp deadline; // 투표글에서만 사용, 후기글에서는 null - List userVote; // 투표글에서 사용자가 투표완료시 투표한 후보 + List userVote; // 투표글에서 사용자가 투표완료시 투표한 후보 List percent; // 투표글에서 사용자가 투표 완료시 투표한 후보 선택 퍼센트 List voteResult; // 투표글에서 사용자가 투표 완료시 투표인원/총인원 Integer view; @@ -66,8 +64,8 @@ public static class PollPostGetResponse{ String title; String content; LocalDateTime uploadDate; - List pollOption; - List userVote; + List pollOption; + List userVote; Integer gauge; Integer like; Integer comment; @@ -92,7 +90,7 @@ public static class ReviewPostGetResponse{ String title; String content; LocalDateTime uploadDate; - String ReviewPic; + List ReviewPicList; Integer like; Integer comment; Boolean isLike; @@ -127,7 +125,7 @@ public static class PostSummaryListRes { String title; String content; Long post_id; - String file; + List file; Integer like; Integer comment_cnt; LocalDateTime created_at; diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 5bbd203..722eeb9 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -29,7 +29,6 @@ public static class UserJoinRequest { boolean agree_marketing; LocalDate birth; boolean is_deleted; - String image; Integer point; String kakao; Integer like; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 66bf71e..9137343 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,8 @@ spring: + servlet: + multipart: + max-file-size: 200MB + max-request-size: 200MB redis: host: ${REDIS_HOSTNAME} port: ${REDIS_PORT} @@ -30,7 +34,7 @@ cloud: path: user: users post: posts - report: reports + candidate: candidates region: static: ap-northeast-2 stack: From 277f7e0052352d7a39b65c888ba6a2d0dabfa0fc Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 8 Feb 2024 13:25:43 +0900 Subject: [PATCH 142/255] =?UTF-8?q?#86=20Chore:=20=EC=93=B8=EB=8D=B0?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/Post.java | 3 - src/main/java/friend/spring/domain/User.java | 3 - .../friend/spring/service/PostService.java | 2 - .../spring/service/PostServiceImpl.java | 77 +------------------ .../web/controller/PostRestController.java | 6 -- .../friend/spring/web/dto/PostRequestDTO.java | 2 - 6 files changed, 1 insertion(+), 92 deletions(-) diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index f07bb4d..5966077 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -50,9 +50,6 @@ public class Post extends BaseEntity { @Column(nullable = true) private Integer point; -// @Column(nullable = true) -// private String file; - @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 731637f..4c8fc3c 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -58,9 +58,6 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true) private Boolean agree_info; -// @Column(nullable = true) -// private String image; - @Column(nullable = true)//잠시 true로 수정 private Boolean is_deleted; diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index 37522f3..1ba8ac9 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -27,8 +27,6 @@ public interface PostService { Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2, List file); -// Candidate createCandidate(Long postId, PollOptionDTO.PollOptionReq request, HttpServletRequest request2); - Candidate createCandidate(Long postId, String optionString, MultipartFile optionImg, HttpServletRequest request2); Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user); diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 0737140..fcb9c6b 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -95,33 +95,22 @@ public void checkPostScrap(Boolean flag) { @Override @Transactional public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2, List file) { - System.out.println("테스트0"); - Long userId = jwtTokenProvider.getCurrentUser(request2); - System.out.println("테스트0.5"); - Post newPost= PostConverter.toPost(request); - System.out.println("테스트0.7"); User user=userRepository.findById(userId) .orElseThrow(()->new RuntimeException("\""+userId+"\"해당 유저가 없습니다")); - System.out.println("테스트0.9"); newPost.setUser(user); - System.out.println("테스트1"); - // 글 첨부파일 사진 저장 s3Service.uploadPostImages(file, S3ImageType.POST, newPost); - System.out.println("테스트2"); - //일반 투표 api if(newPost.getPostType()==VOTE){ newPost.setCategory(categoryRepository.findByName(request.getCategory())); } - System.out.println("테스트3"); -// if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL&&pollOption!=null){ + if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL){ //포인트 차감 관련 코드 if(request.getPoint()!=null) { @@ -136,7 +125,6 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque newPoint.setUser(user); pointRepository.save(newPoint); } - System.out.println("테스트4"); General_poll generalPoll = General_poll.builder() .pollTitle(request.getPollTitle()) @@ -146,26 +134,10 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque generalPoll.setMultipleChoice(request.getMultipleChoice()); } newPost.setGeneralPoll(generalPoll); - System.out.println("테스트5"); generalPollRepository.save(generalPoll); - System.out.println("테스트6"); - -// for (PollOptionDTO.PollOptionReq option : pollOption) { -// Candidate candidate = Candidate.builder() -// .name(option.getOptionString()) -// .build(); -// -// File candidateFile = s3Service.uploadSingleImage(option.getOptionImg(), S3ImageType.CANDIDATE, null, candidate); -// candidate.setFile(candidateFile); -// -// candidate.setGeneralPoll(generalPoll); -// candidateRepository.save(candidate); -// } - System.out.println("테스트7"); } //카드 투표 api -// if(newPost.getPostType()==VOTE&&newPost.getVoteType()==CARD&&pollOption!=null){ if(newPost.getPostType()==VOTE&&newPost.getVoteType()==CARD){ //포인트 차감 관련 코드 if(request.getPoint()!=null) { @@ -180,7 +152,6 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque newPoint.setUser(user); pointRepository.save(newPoint); } - System.out.println("테스트8"); if(!checkPoint(request, user)&&request.getPoint()!=null){ throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); @@ -195,20 +166,6 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque } newPost.setCardPoll(cardPoll); cardPollRepository.save(cardPoll); - System.out.println("테스트9"); - -// for (PollOptionDTO.PollOptionReq option : pollOption) { -// Candidate candidate = Candidate.builder() -// .name(option.getOptionString()) -// .build(); -// -// File candidateFile = s3Service.uploadSingleImage(option.getOptionImg(), S3ImageType.CANDIDATE, null, candidate); -// candidate.setFile(candidateFile); -// -// candidate.setCardPoll(cardPoll); -// candidateRepository.save(candidate); -// } - System.out.println("테스트10"); } //게이지 투표 api if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GAUGE){ @@ -249,42 +206,10 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque newPost.setParentPost(parent); } - System.out.println("테스트11"); return postRepository.save(newPost); } -// @Override -// public Candidate createCandidate(Long postId, PollOptionDTO.PollOptionReq request, HttpServletRequest request2) { -// Post newPost = postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); -// -// Long userId = jwtTokenProvider.getCurrentUser(request2); -// User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); -// if (!newPost.getUser().equals(user)) { // 이 글을 쓴 사용자인지 검증 -// this.checkPostWriterUser(false); -// } -// -// Candidate candidate = Candidate.builder() -// .name(request.getOptionString()) -// .build(); -// -// File candidateFile = s3Service.uploadSingleImage(request.getOptionImg(), S3ImageType.CANDIDATE, null, candidate); -// candidate.setFile(candidateFile); -// -// // 일반 투표 -// if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL) { -// General_poll generalPoll = generalPollRepository.findById(newPost.getGeneralPoll().getId()).orElseThrow(() -> new GeneralException(POST_GENERAL_POLL_NOT_FOUND)); -// candidate.setGeneralPoll(generalPoll); -// } -// // 카드 투표 -// else { -// Card_poll cardPoll = cardPollRepository.findById(newPost.getCardPoll().getId()).orElseThrow(() -> new GeneralException(POST_CARD_POLL_NOT_FOUND)); -// candidate.setCardPoll(cardPoll); -// } -// -// return candidateRepository.save(candidate); -// } - @Override @Transactional public Candidate createCandidate(Long postId, String optionString, MultipartFile optionImg, HttpServletRequest request2) { diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 48e26ed..a77dcac 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -38,7 +38,6 @@ public class PostRestController { private final PostQueryService postQueryService; private final PostRepository postRepository; private final JwtTokenService jwtTokenService; -// @PostMapping(value = "/", consumes = "multipart/form-data") @PostMapping(value = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @Operation(summary = "글 작성 API", description = "글을 추가 합니다.") @Parameters({ @@ -50,7 +49,6 @@ public class PostRestController { @Parameter(name="postVoteType", description=" 투표 종류
1 : GENERAL
2 : GAUGE
3 : CARD
해당 사항 없을시 null"), @Parameter(name="pollTitle", description=" 투표 제목"), @Parameter(name="multipleChoice", description=" 복수 선택 여부"), -// @Parameter(name="pollOption", description=" 투표 후보{optionString : string, optionImg : string}
해당 사항 없을시 null"), @Parameter(name="parent_id", description=" 원글(후기글 경우) id
해당 사항 없을시 null"), @Parameter(name="deadline", description=" 투표 마감 시간
해당 사항 없을시 null"), @Parameter(name="point", description=" 포인트
해당 사항 없을시 null") @@ -58,10 +56,8 @@ public class PostRestController { }) public ApiResponse join(@RequestPart(value = "request") @Valid PostRequestDTO.AddPostDTO request, @RequestPart(value = "file", required = false) List file, -// @RequestPart(value = "pollOptionImages", required = false) List pollOptionFiles, @RequestHeader("atk") String atk, HttpServletRequest request2){ - System.out.println("테스트000000"); Post post= postService.joinPost(request,request2, file); return ApiResponse.onSuccess(PostConverter.toAddPostResultDTO(post)); } @@ -74,12 +70,10 @@ public ApiResponse join(@RequestPart(value = " }) public ApiResponse createCandidate( @PathVariable(name="post-id") Long postId, -// @RequestBody PollOptionDTO.PollOptionReq request, @RequestParam String optionString, @RequestParam(required = false) MultipartFile optionImg, @RequestHeader("atk") String atk, HttpServletRequest request2) { -// Candidate candidate = postService.createCandidate(postId, request,request2); Candidate candidate = postService.createCandidate(postId, optionString, optionImg,request2); return ApiResponse.onSuccess(CandidateConverter.toAddCandidateResultDTO(candidate)); } diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index 7a4bc3d..fa99c7e 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -27,12 +27,10 @@ public static class AddPostDTO{ Integer postVoteType;// 1: general, 2: gauge String pollTitle; Boolean multipleChoice; -// List pollOption; Long parent_id; @NotBlank Timestamp deadline; Integer point; -// List file; } @Getter public static class ReviewPostGetDTO{ From 05c4ec9e1fee9eb9afbd7930f65b4a7a54508339 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 8 Feb 2024 16:46:11 +0900 Subject: [PATCH 143/255] =?UTF-8?q?#86=20Chore:=20=EA=B8=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EC=8B=9C=20=ED=8C=8C=EC=9D=BC=20=EC=B2=A8=EB=B6=80?= =?UTF-8?q?=20null=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/service/PostServiceImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index fcb9c6b..07e34d8 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -103,7 +103,11 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque newPost.setUser(user); // 글 첨부파일 사진 저장 - s3Service.uploadPostImages(file, S3ImageType.POST, newPost); + if (file != null) { + s3Service.uploadPostImages(file, S3ImageType.POST, newPost); + } + + //일반 투표 api if(newPost.getPostType()==VOTE){ From 9e6b2d75e56817b5bd3661185d4d21fba44538fd Mon Sep 17 00:00:00 2001 From: ls-rain Date: Thu, 8 Feb 2024 19:07:53 +0900 Subject: [PATCH 144/255] =?UTF-8?q?#63=20Feat=20:=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=ED=95=9C=20=EA=B2=8C=EC=8B=9C=EB=AC=BC(=EB=82=B4=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC,=20=EB=AA=A8=EB=93=A0=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EB=AC=BC)=20=EC=A4=91=EA=B0=84=EC=A0=80=EC=9E=A5=20NP?= =?UTF-8?q?E=20=EB=B0=9C=EC=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/MyPageConverter.java | 37 +++++++-- .../repository/PostScrapRepository.java | 19 +++++ .../friend/spring/service/MyPageService.java | 7 +- .../spring/service/MyPageServiceImpl.java | 52 +++++++----- .../web/controller/MyPageController.java | 52 ------------ .../web/controller/MyPageRestController.java | 79 +++++++++++++++++++ .../web/controller/UserRestController.java | 2 + .../spring/web/dto/MyPageResponseDTO.java | 32 +++++++- 8 files changed, 198 insertions(+), 82 deletions(-) delete mode 100644 src/main/java/friend/spring/web/controller/MyPageController.java create mode 100644 src/main/java/friend/spring/web/controller/MyPageRestController.java diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index 88d9b70..c1a53d9 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -7,20 +7,47 @@ import friend.spring.web.dto.MyPageResponseDTO; import org.springframework.data.domain.Page; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import static java.util.Calendar.HOUR; +import static java.util.Calendar.SECOND; +import static java.util.Calendar.MINUTE; public class MyPageConverter { + public static MyPageResponseDTO.CategoryResDTO toCategoryResDTO(Category category){ + return MyPageResponseDTO.CategoryResDTO.builder() + .category(category.getName()) + .build(); + } public static MyPageResponseDTO.SavedCategoryResDTO toSavedCategoryResDTO(List categoryList){ - List categoryNameList = new ArrayList<>(); - categoryNameList = categoryList.stream().map(category -> { - return category.getName(); - }).collect(Collectors.toList()); - + List categoryNameList = categoryList.stream() + .map(MyPageConverter::toCategoryResDTO).collect(Collectors.toList()); return MyPageResponseDTO.SavedCategoryResDTO.builder() .postCategoryList(categoryNameList).build(); } + + public static MyPageResponseDTO.SavedPostResDTO toSavedPostResDTO(Post post){ + long diffTime = post.getCreatedAt().until(LocalDateTime.now(), ChronoUnit.SECONDS); // now보다 이후면 +, 전이면 - + diffTime = diffTime / SECOND; + diffTime = diffTime / MINUTE; + diffTime = diffTime / HOUR; + return MyPageResponseDTO.SavedPostResDTO.builder() + .ago(diffTime) + .title(post.getTitle()) + .content(post.getContent()) + .postLike(post.getPostLikeList().size()) + .comment(post.getCommentList().size()).build(); + } + + public static MyPageResponseDTO.SavedAllPostResDTO toSavedAllPostResDTO(Page postList){ + List savedAllPostList = postList.stream().map(MyPageConverter::toSavedPostResDTO).collect(Collectors.toList()); + return MyPageResponseDTO.SavedAllPostResDTO.builder() + .postList(savedAllPostList).build(); + } } diff --git a/src/main/java/friend/spring/repository/PostScrapRepository.java b/src/main/java/friend/spring/repository/PostScrapRepository.java index ffaa8d6..960742f 100644 --- a/src/main/java/friend/spring/repository/PostScrapRepository.java +++ b/src/main/java/friend/spring/repository/PostScrapRepository.java @@ -1,11 +1,30 @@ package friend.spring.repository; +import friend.spring.domain.Category; +import friend.spring.domain.Post; +import friend.spring.domain.User; import friend.spring.domain.mapping.Post_scrap; +import lombok.Value; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import java.util.List; import java.util.Optional; public interface PostScrapRepository extends JpaRepository { Optional findByPostIdAndUserId(Long postId, Long userId); + + List findAllByUser(User user); + + // 사용자가 스크랩한 모든 글을 최신순으로 정렬하여 페이징하여 조회 + @Query("SELECT p FROM Post p JOIN p.postScrapList s WHERE s.user.id = :userId ORDER BY p.createdAt DESC") + Page findPostsByUserIdOrderByCreatedAtDesc(Long userId, Pageable pageable); + + // 사용자가 스크랩한 모든 글을 조회수 순으로 정렬하여 페이징하여 조회 + @Query("SELECT p FROM Post p JOIN p.postScrapList s WHERE s.user.id = :userId ORDER BY p.view DESC") + Page findPostsByUserIdOrderByPostViewDesc(Long userId, Pageable pageable); } diff --git a/src/main/java/friend/spring/service/MyPageService.java b/src/main/java/friend/spring/service/MyPageService.java index 6b5c187..491cedf 100644 --- a/src/main/java/friend/spring/service/MyPageService.java +++ b/src/main/java/friend/spring/service/MyPageService.java @@ -2,15 +2,16 @@ import friend.spring.domain.Category; import friend.spring.domain.Post; -import friend.spring.domain.enums.PostCategory; import friend.spring.domain.mapping.Post_scrap; import org.springframework.data.domain.Page; import java.util.List; +import java.util.Optional; import java.util.Set; public interface MyPageService { void checkPost(Boolean flag); - void checkScrapPost(Boolean flag); - List getScrapList(Long userId); + List getCategoryList(Long userId); + + Page getAllPostList(Long userId, Integer page, Integer sort); } diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index ec490d6..18e4c20 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -1,30 +1,42 @@ package friend.spring.service; +import friend.spring.apiPayload.GeneralException; import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.apiPayload.handler.PostHandler; +import friend.spring.converter.MyPageConverter; import friend.spring.domain.Category; import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.mapping.Post_scrap; import friend.spring.repository.CategoryRepository; +import friend.spring.repository.PostRepository; import friend.spring.repository.PostScrapRepository; import friend.spring.repository.UserRepository; +import friend.spring.web.dto.MyPageResponseDTO; +import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; @Service @RequiredArgsConstructor @Transactional +@Slf4j public class MyPageServiceImpl implements MyPageService{ private final UserRepository userRepository; + private final PostService postService; private final UserService userService; + private final PostRepository postRepository; private final CategoryRepository categoryRepository; private final PostScrapRepository postScrapRepository; @Override @@ -33,32 +45,30 @@ public void checkPost(Boolean flag) { throw new PostHandler(ErrorStatus.POST_CATGORY_NOT_FOUND); } } + //저장한 게시물 @Override - public void checkScrapPost(Boolean flag) { - if (!flag) { - throw new PostHandler(ErrorStatus.POST_SAVED_NOT_FOUND); + public List getCategoryList(Long userId) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + List scrapList = user.getPostScrapList(); + if (scrapList.isEmpty()) { + postService.checkPostScrap(false); + } + List categoryList = scrapList.stream() + .map(Post_scrap::getPost).filter(Objects::nonNull) + .map(Post::getCategory).filter(Objects::nonNull).collect(Collectors.toList()); + return categoryList; } - } - //저장한 게시물 @Override - public List getScrapList(Long userId) { - Optional optionalUser = userRepository.findById(userId); - if (optionalUser.isEmpty()){ - userService.checkUser(false); + public Page getAllPostList(Long userId, Integer page, Integer sort) { + if (sort == 0){ + Page scrapListByView = postScrapRepository.findPostsByUserIdOrderByPostViewDesc(userId, PageRequest.of(page, 10)); + return scrapListByView; } - User user = optionalUser.get(); - List postScrapList = user.getPostScrapList().stream() - .map(postScrap -> { - return postScrapRepository.findById(postScrap.getId()).orElseThrow(() -> new PostHandler(ErrorStatus.POST_SAVED_NOT_FOUND)); - }).collect(Collectors.toList()); - if (postScrapList.isEmpty()){ - checkScrapPost(false); + else if (sort == 1){ + Page scrapListByRecent = postScrapRepository.findPostsByUserIdOrderByCreatedAtDesc(userId, PageRequest.of(page, 10)); + return scrapListByRecent; } - - List categoryList = postScrapList.stream().map(postScrap -> { - return postScrap.getPost().getPostCategory(); - }).collect(Collectors.toList()); - return categoryList; + else return null; } } diff --git a/src/main/java/friend/spring/web/controller/MyPageController.java b/src/main/java/friend/spring/web/controller/MyPageController.java deleted file mode 100644 index d09ef63..0000000 --- a/src/main/java/friend/spring/web/controller/MyPageController.java +++ /dev/null @@ -1,52 +0,0 @@ -package friend.spring.web.controller; - -import friend.spring.apiPayload.ApiResponse; -import friend.spring.converter.MyPageConverter; -import friend.spring.domain.Category; -import friend.spring.domain.mapping.Post_scrap; -import friend.spring.service.MyPageService; -import friend.spring.service.PostService; -import friend.spring.service.UserService; -import friend.spring.web.dto.MyPageResponseDTO; -import friend.spring.web.dto.PostResponseDTO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; -import java.util.Set; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/user/my-page") -public class MyPageController { - private UserService userService; - private PostService postService; - private MyPageService myPageService; - - //저장한 게시물(내 카테고리) 조회 - @GetMapping("/post") - @Operation(summary = "사용자 글 카테고리 조회 API",description = "사용자의 저장 글 카테고리 목록을 집합으로 조회하는 API입니다.") - @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "회원정보가 존재하지 않습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004",description = "카테고리를 찾을 수 없습니다.") - - }) - @Parameters({ - @Parameter(name = "userId", description = "RequestHeader - 로그인한 사용자 아이디(accessToken으로 변경 예정)") - }) - public ApiResponse getCategorySet( - @RequestHeader(name = "userId") Long userId){ - List scrapList = myPageService.getScrapList(userId); - return ApiResponse.onSuccess(MyPageConverter.toSavedCategoryResDTO(scrapList)); - } - -} diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java new file mode 100644 index 0000000..0fea6b2 --- /dev/null +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -0,0 +1,79 @@ +package friend.spring.web.controller; + +import friend.spring.apiPayload.ApiResponse; +import friend.spring.converter.MyPageConverter; +import friend.spring.domain.Category; +import friend.spring.domain.Post; +import friend.spring.service.JwtTokenService; +import friend.spring.service.MyPageService; +import friend.spring.service.PostService; +import friend.spring.service.UserService; +import friend.spring.web.dto.MyPageResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/user/my-page") +public class MyPageRestController { + private UserService userService; + private PostService postService; + private MyPageService myPageService; + + private final JwtTokenService jwtTokenService; + + //저장한 게시물(내 카테고리) 조회 + @GetMapping("/post") + @Operation(summary = "사용자 글 카테고리 조회 API",description = "사용자의 저장 글 카테고리 목록을 집합으로 조회하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "회원정보가 존재하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004",description = "카테고리를 찾을 수 없습니다.") + + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) + public ApiResponse getCategorySet( + @RequestHeader(name = "atk") String atk, + HttpServletRequest request){ + Long userId = jwtTokenService.JwtToId(request); + List categoryList = myPageService.getCategoryList(userId); + return ApiResponse.onSuccess(MyPageConverter.toSavedCategoryResDTO(categoryList)); + } + + //저장한 게시물(모든게시물) + @GetMapping("/post/all") + @Operation(summary = "저장한 게시물(모든게시물) 조회 API",description = "사용자의 전체 저장 글을 조회하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "회원정보가 존재하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "글을 찾을 수 없습니다.."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4005",description = "저장한 글이 없습니다.") + + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), + @Parameter(name = "sort", description = "query string(RequestParam) - 조회순(0)인지 최신순(1)인지 가리키는 sort 변수") + + }) + public ApiResponse getAllSavedPosts( + @RequestParam(name = "page", defaultValue = "0") Integer page, + @RequestParam(name = "sort", defaultValue = "0") Integer sort, + @RequestHeader(name = "atk") String atk, + HttpServletRequest request){ + Long userId = jwtTokenService.JwtToId(request); + Page allPostList = myPageService.getAllPostList(userId, page, sort); + return ApiResponse.onSuccess(MyPageConverter.toSavedAllPostResDTO(allPostList)); + } + +} diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index c5e6304..28cdb1a 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -88,6 +88,7 @@ public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailS }) @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)") }) public ApiResponse getQuestion( @@ -111,6 +112,7 @@ public ApiResponse getQuestion( }) @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)") }) public ApiResponse getAnswer( diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index 421a36f..7dbd491 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -5,15 +5,45 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.time.LocalDateTime; import java.util.List; import java.util.Set; public class MyPageResponseDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class CategoryResDTO{ + String category; + } + @Builder @Getter @NoArgsConstructor @AllArgsConstructor public static class SavedCategoryResDTO{ - List postCategoryList; + List postCategoryList; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class SavedPostResDTO{ + Long ago; + String title; + String content; + Integer postLike; + Integer comment; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class SavedAllPostResDTO{ + List postList; } } From 335e4fe66c97f278bc17e12c2929e47db6df4c7f Mon Sep 17 00:00:00 2001 From: ls-rain Date: Thu, 8 Feb 2024 21:22:50 +0900 Subject: [PATCH 145/255] =?UTF-8?q?#63=20Feat=20:=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=ED=95=9C=20=EA=B2=8C=EC=8B=9C=EB=AC=BC(=EB=82=B4=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC,=20=EB=AA=A8=EB=93=A0=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EB=AC=BC)=20=EC=A4=91=EA=B0=84=EC=A0=80=EC=9E=A5=20NP?= =?UTF-8?q?E=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/service/MyPageServiceImpl.java | 2 +- .../friend/spring/web/controller/MyPageRestController.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index 18e4c20..21ed764 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -55,7 +55,7 @@ public List getCategoryList(Long userId) { } List categoryList = scrapList.stream() .map(Post_scrap::getPost).filter(Objects::nonNull) - .map(Post::getCategory).filter(Objects::nonNull).collect(Collectors.toList()); + .map(Post::getCategory).filter(Objects::nonNull).distinct().collect(Collectors.toList()); return categoryList; } diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index 0fea6b2..b2555dd 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -24,9 +24,9 @@ @RequiredArgsConstructor @RequestMapping("/user/my-page") public class MyPageRestController { - private UserService userService; - private PostService postService; - private MyPageService myPageService; + private final UserService userService; + private final PostService postService; + private final MyPageService myPageService; private final JwtTokenService jwtTokenService; From c586d5244a08a38eb249c2efcf468fcc7ce8ab34 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 9 Feb 2024 09:08:58 +0900 Subject: [PATCH 146/255] =?UTF-8?q?#86=20Chore:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=83=81=EC=84=B8=20=EB=B3=B4=EA=B8=B0=20=EC=82=AC?= =?UTF-8?q?=EC=A7=84=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/PostConverter.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 128abaf..e9cfb94 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -99,11 +99,9 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ .map(Candidate::getName) .findFirst(); String candidateName=name.get(); - Optional image = parentPost.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> candidate.getId().equals(id)) - .map(Candidate::getFile) - .findFirst(); - String candidateImage=image.get().getUrl(); + String candidateImage = parentPollDTO.getCandidateImage(); + + parentPollDTO.setCandidateName(candidateName); parentPollDTO.setCandidateImage(candidateImage); From 8c00cdea8da401725a0baa8d0beaaa7878f654f6 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 9 Feb 2024 11:21:46 +0900 Subject: [PATCH 147/255] =?UTF-8?q?#29=20Refactor:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20=EC=83=81=ED=83=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/converter/CommentConverter.java | 10 ++++++++++ .../java/friend/spring/web/dto/CommentResponseDTO.java | 1 + 2 files changed, 11 insertions(+) diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index 4593655..e4a7e23 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -3,6 +3,7 @@ import friend.spring.domain.Comment; import friend.spring.domain.Post; import friend.spring.domain.User; +import friend.spring.domain.enums.CommentState; import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.web.dto.CommentRequestDTO; @@ -18,6 +19,7 @@ public static Comment toComment(CommentRequestDTO.commentCreateReq request, Post .post(post) .content(request.getContent()) .parentComment(parentComment) + .state(CommentState.POSTING) .build(); } @@ -59,6 +61,13 @@ public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment) userPhoto = comment.getUser().getFile().getUrl(); } + boolean isDeleted; + if (comment.getState().equals(CommentState.DELETED)) { + isDeleted = true; + } else { + isDeleted = false; + } + return CommentResponseDTO.commentGetRes.builder() .commentId(comment.getId()) .content(comment.getContent()) @@ -70,6 +79,7 @@ public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment) .parentCommentId(parentCommentId) .commentLike(comment.getCommentLikeList().size()) .childrenComments(subComments) + .isDeleted(isDeleted) .build(); } diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index 1c7d760..11634e5 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -41,6 +41,7 @@ public static class commentGetRes { Long parentCommentId; Integer commentLike; List childrenComments; + Boolean isDeleted; // 댓글 삭제 여부 } @Builder From 2d22ff7ea0dcf313004ff80e394f3463cb7afd23 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 9 Feb 2024 22:26:38 +0900 Subject: [PATCH 148/255] =?UTF-8?q?#29=20Refactor:=20Cors=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95(WebMvcConfigurer)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/config/CorsConfig.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/friend/spring/config/CorsConfig.java diff --git a/src/main/java/friend/spring/config/CorsConfig.java b/src/main/java/friend/spring/config/CorsConfig.java new file mode 100644 index 0000000..3712175 --- /dev/null +++ b/src/main/java/friend/spring/config/CorsConfig.java @@ -0,0 +1,18 @@ +package friend.spring.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class CorsConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowedMethods("GET", "POST", "PUT", "PATCH", "OPTIONS") + .allowedHeaders("headers") + .maxAge(3000); + } +} \ No newline at end of file From 3e66a907b0d33e24651f99eb4592e2796d79b3bf Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 9 Feb 2024 22:39:45 +0900 Subject: [PATCH 149/255] =?UTF-8?q?#29=20Refactor:=20Cors=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/config/CorsConfig.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/friend/spring/config/CorsConfig.java b/src/main/java/friend/spring/config/CorsConfig.java index 3712175..fc8c27e 100644 --- a/src/main/java/friend/spring/config/CorsConfig.java +++ b/src/main/java/friend/spring/config/CorsConfig.java @@ -11,8 +11,6 @@ public class CorsConfig implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") - .allowedMethods("GET", "POST", "PUT", "PATCH", "OPTIONS") - .allowedHeaders("headers") - .maxAge(3000); + .allowedMethods("*"); } } \ No newline at end of file From fa2d37c47d2395ff6b9cc6733e9624a0d4acbb7c Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 9 Feb 2024 22:50:44 +0900 Subject: [PATCH 150/255] =?UTF-8?q?#29=20Refactor:=20Cors=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/config/CorsConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/config/CorsConfig.java b/src/main/java/friend/spring/config/CorsConfig.java index fc8c27e..8b6174d 100644 --- a/src/main/java/friend/spring/config/CorsConfig.java +++ b/src/main/java/friend/spring/config/CorsConfig.java @@ -11,6 +11,7 @@ public class CorsConfig implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") - .allowedMethods("*"); + .allowedMethods("*") + .exposedHeaders("*"); } } \ No newline at end of file From 38a5805a25eca6fe55dec3564cb00373a9ae9632 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 9 Feb 2024 22:52:25 +0900 Subject: [PATCH 151/255] =?UTF-8?q?#29=20Refactor:=20Cors=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/config/CorsConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/friend/spring/config/CorsConfig.java b/src/main/java/friend/spring/config/CorsConfig.java index 8b6174d..3ce5a7e 100644 --- a/src/main/java/friend/spring/config/CorsConfig.java +++ b/src/main/java/friend/spring/config/CorsConfig.java @@ -11,6 +11,8 @@ public class CorsConfig implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") + .allowedOriginPatterns("*") + .allowedHeaders("*") .allowedMethods("*") .exposedHeaders("*"); } From f917808bde0ebee5b075d1829f5df04d7c6266e0 Mon Sep 17 00:00:00 2001 From: hjh Date: Sat, 10 Feb 2024 04:52:01 +0900 Subject: [PATCH 152/255] =?UTF-8?q?#95=20Feat:=20=EC=A0=9C=EC=95=BD?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=20=EC=84=A4=EC=A0=95,=20=EC=9E=90=EC=8B=A0?= =?UTF-8?q?=EC=9D=B4=20=EC=93=B4=20=EA=B8=80=20=EC=83=81=EC=84=B8=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=EC=8B=9C=201=EB=93=B1=20=ED=9B=84=EB=B3=B4=EB=A7=8C?= =?UTF-8?q?=20=EB=82=98=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95,?= =?UTF-8?q?=20=ED=88=AC=ED=91=9C=20=EC=97=AC=EB=B6=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../apiPayload/code/status/ErrorStatus.java | 6 + .../spring/converter/PostConverter.java | 105 ++++++++++++++++++ .../java/friend/spring/domain/Card_poll.java | 13 ++- .../java/friend/spring/domain/Gauge_poll.java | 14 ++- .../friend/spring/domain/General_poll.java | 12 +- src/main/java/friend/spring/domain/Post.java | 10 ++ .../spring/service/PostQueryService.java | 2 +- .../spring/service/PostQueryServiceImpl.java | 19 ++-- .../spring/service/PostServiceImpl.java | 62 ++++++++++- .../spring/service/VoteServiceImpl.java | 18 +-- .../web/controller/CommentRestController.java | 3 +- .../web/controller/PostRestController.java | 9 +- .../web/controller/UserRestController.java | 2 +- .../friend/spring/web/dto/PostRequestDTO.java | 22 ++-- .../spring/web/dto/PostResponseDTO.java | 5 +- 16 files changed, 266 insertions(+), 37 deletions(-) diff --git a/build.gradle b/build.gradle index 21d5080..46b8f10 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,7 @@ dependencies { compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' + implementation 'org.springframework.boot:spring-boot-starter-validation' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'org.springdoc:springdoc-openapi-ui:1.6.15' implementation 'io.springfox:springfox-swagger2:2.9.2' diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index f62e965..4e74d3c 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -35,6 +35,12 @@ public enum ErrorStatus implements BaseErrorCode { POST_SCRAP_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4004", "글에 대한 스크랩 데이터를 찾을 수 없습니다."), POST_GENERAL_POLL_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4005", "글에 대한 일반 투표 데이터를 찾을 수 없습니다."), POST_CARD_POLL_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4006", "글에 대한 카드 투표 데이터를 찾을 수 없습니다."), + TITLE_TEXT_LIMIT(HttpStatus.BAD_REQUEST,"POST4007","최소 5자 이상, 30자 미만 입력해 주세요"), + CONTENT_TEXT_LIMIT(HttpStatus.BAD_REQUEST,"POST4008","최소 5자 이상, 1000자 미만 입력해 주세요"), + CANDIDATE_TEXT_LIMIT(HttpStatus.BAD_REQUEST,"POST4009","최소 1자 이상, 30자 미만 입력해 주세요"), + DEADLINE_LIMIT(HttpStatus.BAD_REQUEST,"POST4010","최소 1분~최대30일로 입력해 주세요"), + CANDIDATE_NOT_FOUND(HttpStatus.NOT_FOUND,"POST4011","후보를 찾을 수 없습니다"), + TOO_MUCH_FIXED(HttpStatus.NOT_FOUND,"POST4012","이미 2회 이상 수정 했습니다"), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index e9cfb94..ea13be7 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -228,6 +228,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B List percent=null; List voteResult=null; Integer value=null; + Boolean isVote=false; Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); if(post.getUser().getId().equals(userId)){ @@ -254,12 +255,15 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B if(post.getVoteType()==PostVoteType.GAUGE){ if(engage){ value=post.getGaugePoll().getGauge(); + isVote=true; } return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) + .OnGoing(post.getGaugePoll().getVoteOnGoing()) + .isVoted(isVote) .file(FileConverter.toFileDTO(post.getFileList())) .gauge(value) .point(post.getPoint()) @@ -318,12 +322,48 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B return String.format("%d/%d", selectionCount, totalVotes); }) .collect(Collectors.toList()); + isVote=true; + if(myPost){ + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.values().stream() + .mapToDouble(aLong -> (double) aLong / totalVotes) + .max(); + + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + userChoiceList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + + percent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) + voteResult = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + } } return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) + .OnGoing(post.getGeneralPoll().getVoteOnGoing()) + .isVoted(isVote) .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getGeneralPoll().getPollTitle()) .pollOption(pollOptionDTOList) @@ -370,6 +410,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .flatMap(vote -> vote.getSelect_list().stream()) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + // 사용자가 선택한 후보의 선택률 계산 percent = userSelectedCandidateIds.stream() .map(candidateId -> { @@ -385,12 +426,76 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B return String.format("%d/%d", selectionCount, totalVotes); }) .collect(Collectors.toList()); + isVote=true; + if(myPost){ + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.values().stream() + .mapToDouble(aLong -> (double) aLong / totalVotes) + .max(); + + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + + percent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) + voteResult = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + } + if(myPost){ + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .max(); + + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + userChoiceList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + + percent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) + voteResult = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + } } return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) + .OnGoing(post.getCardPoll().getVoteOnGoing()) + .isVoted(isVote) .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getCardPoll().getPollTitle()) .pollOption(pollOptionDTOList) diff --git a/src/main/java/friend/spring/domain/Card_poll.java b/src/main/java/friend/spring/domain/Card_poll.java index 0e97de6..d1ccbb8 100644 --- a/src/main/java/friend/spring/domain/Card_poll.java +++ b/src/main/java/friend/spring/domain/Card_poll.java @@ -27,7 +27,11 @@ public class Card_poll extends BaseEntity { @Column(nullable = true) @Builder.Default - private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. + private LocalDateTime deadline= LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. + + @Column(nullable = true) + @Builder.Default + private Boolean VoteOnGoing=true; @Builder.Default @OneToMany(mappedBy = "cardPoll", cascade = CascadeType.ALL) @@ -44,6 +48,13 @@ public class Card_poll extends BaseEntity { public void setPost(Post post) { this.post = post; } + + public void setDeadline(LocalDateTime deadline){ + this.deadline=deadline; + } + public void setVoteOnGoing(Boolean voteOnGoing){ + this.VoteOnGoing=voteOnGoing; + } public void setMultipleChoice(Boolean multipleChoice){ this.multipleChoice=multipleChoice; } diff --git a/src/main/java/friend/spring/domain/Gauge_poll.java b/src/main/java/friend/spring/domain/Gauge_poll.java index 5796428..fcb55cd 100644 --- a/src/main/java/friend/spring/domain/Gauge_poll.java +++ b/src/main/java/friend/spring/domain/Gauge_poll.java @@ -28,7 +28,11 @@ public class Gauge_poll extends BaseEntity { @Builder.Default @Column(nullable = true) - private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. + private LocalDateTime deadline= LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. + + @Column(nullable = true) + @Builder.Default + private Boolean VoteOnGoing=true; @OneToOne(mappedBy = "gaugePoll", cascade = CascadeType.ALL) @JoinColumn(name = "post_id") @@ -42,6 +46,14 @@ public void setPost(Post post) { this.post = post; } + public void setDeadline(LocalDateTime deadline){ + this.deadline=deadline; + } + + public void setVoteOnGoing(Boolean voteOnGoing){ + this.VoteOnGoing=voteOnGoing; + } + public void setGauge(Integer gauge) { this.gauge = gauge; } diff --git a/src/main/java/friend/spring/domain/General_poll.java b/src/main/java/friend/spring/domain/General_poll.java index 5be6a26..9d4bdd1 100644 --- a/src/main/java/friend/spring/domain/General_poll.java +++ b/src/main/java/friend/spring/domain/General_poll.java @@ -28,7 +28,11 @@ public class General_poll extends BaseEntity { @Column(nullable = true) @Builder.Default - private Timestamp deadline= Timestamp.valueOf(LocalDateTime.now().plusHours(1)); // 디폴트 시간 1시간 설정. + private LocalDateTime deadline= LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. + + @Column(nullable = true) + @Builder.Default + private Boolean VoteOnGoing=true; @Builder.Default @OneToMany(mappedBy = "generalPoll", cascade = CascadeType.ALL) @@ -46,6 +50,12 @@ public void setPost(Post post) { this.post = post; } + public void setDeadline(LocalDateTime deadline){ + this.deadline=deadline; + } + public void setVoteOnGoing(Boolean voteOnGoing){ + this.VoteOnGoing=voteOnGoing; + } public void setMultipleChoice(Boolean multipleChoice){ this.multipleChoice=multipleChoice; } diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 5966077..0538b5e 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -10,6 +10,7 @@ import lombok.*; import javax.persistence.*; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -50,6 +51,10 @@ public class Post extends BaseEntity { @Column(nullable = true) private Integer point; + @Builder.Default + @Column(nullable = false) + private Integer isFixed=0; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; @@ -162,7 +167,12 @@ public void setContent(String content){ this.content=content; } + public void setIsFixed(Integer isFixed){ + this.isFixed=isFixed; + } + public void setStateDel(){ this.state=PostState.DELETED; } + } diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index c905b20..36fa8db 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -9,7 +9,7 @@ import java.util.Optional; public interface PostQueryService { - Optional getPostDetail(Long postId); + Post getPostDetail(Long postId); Boolean checkEngage(Long userId, Long postId); Post ParentPost(Long parentid); diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 21108d2..fcd20dd 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -1,5 +1,7 @@ package friend.spring.service; +import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.converter.PostConverter; import friend.spring.domain.*; import friend.spring.domain.enums.PostState; @@ -22,6 +24,7 @@ import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -35,11 +38,10 @@ public class PostQueryServiceImpl implements PostQueryService{ private final JwtTokenProvider jwtTokenProvider; @Override @Transactional - public Optional getPostDetail(Long postId){ - Optional postOptional=postRepository.findById(postId); - Post post = postOptional.get(); + public Post getPostDetail(Long postId){ + Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); post.setView(post.getView()+1); - return postOptional; + return post; } @Override @@ -53,7 +55,8 @@ public Boolean checkEngage(Long postId,Long userId){ if(post.getPostType()== PostType.VOTE){ if(post.getVoteType()== PostVoteType.GENERAL){ List vote=generalVoteRepository.findByUserId(userId); - if (!vote.isEmpty()) { // 목록이 비어 있지 않으면 true를 반환 + Boolean isIn=vote.stream().filter(pollPost->pollPost.getGeneralPoll()==post.getGeneralPoll()).collect(Collectors.toList()).isEmpty(); + if (!isIn) { // 목록이 비어 있지 않으면 true를 반환 return true; } } @@ -61,7 +64,8 @@ public Boolean checkEngage(Long postId,Long userId){ if(post.getPostType()== PostType.VOTE){ if(post.getVoteType()== PostVoteType.CARD){ List vote=cardVoteRepository.findByUserId(userId); - if (!vote.isEmpty()) { // 목록이 비어 있지 않으면 true를 반환 + Boolean isIn=vote.stream().filter(pollPost->pollPost.getCardPoll()==post.getCardPoll()).collect(Collectors.toList()).isEmpty(); + if (!isIn) { // 목록이 비어 있지 않으면 true를 반환 return true; } } @@ -69,7 +73,8 @@ public Boolean checkEngage(Long postId,Long userId){ if(post.getPostType()== PostType.VOTE){ if(post.getVoteType()== PostVoteType.GAUGE){ List vote=gaugeVoteRepository.findByUserId(userId); - if (!vote.isEmpty()) { // 목록이 비어 있지 않으면 true를 반환 + Boolean isIn=vote.stream().filter(pollPost->pollPost.getGaugePoll()==post.getGaugePoll()).collect(Collectors.toList()).isEmpty(); + if (!isIn) { // 목록이 비어 있지 않으면 true를 반환 return true; } } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 07e34d8..ab3ebc9 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -24,6 +24,8 @@ import org.springframework.web.multipart.MultipartFile; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.Objects; import javax.servlet.http.HttpServletRequest; import java.util.*; @@ -99,7 +101,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque Post newPost= PostConverter.toPost(request); User user=userRepository.findById(userId) - .orElseThrow(()->new RuntimeException("\""+userId+"\"해당 유저가 없습니다")); + .orElseThrow(()->new GeneralException(USER_NOT_FOUND)); newPost.setUser(user); // 글 첨부파일 사진 저장 @@ -225,6 +227,10 @@ public Candidate createCandidate(Long postId, String optionString, MultipartFile this.checkPostWriterUser(false); } + if (!(!optionString.isEmpty() && optionString.length() < 30)) { // 이 글을 쓴 사용자인지 검증 + throw new GeneralException(CANDIDATE_TEXT_LIMIT); + } + Candidate candidate = Candidate.builder() .name(optionString) .build(); @@ -256,11 +262,61 @@ public void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); if(!user.getId().equals(post.getUser().getId())){ - throw new RuntimeException("수정 권환이 없습니다 글이 없습니다"); + throw new GeneralException(POST_NOT_CORRECT_USER); + } + if(post.getIsFixed()>=2){ + throw new GeneralException(TOO_MUCH_FIXED); + } + if(!(request.getDeadline()==null)) { + LocalDateTime currentDeadLine; + if (post.getVoteType() == GENERAL) { + currentDeadLine = post.getGeneralPoll().getDeadline(); + long daysUntilDeadline = ChronoUnit.DAYS.between(currentDeadLine, request.getDeadline()); + if (request.getDeadline().isBefore(LocalDateTime.now())) { + throw new GeneralException(DEADLINE_LIMIT); + } + if (!(daysUntilDeadline <= 30)) { + throw new GeneralException(DEADLINE_LIMIT); + } + post.getGeneralPoll().setDeadline(request.getDeadline()); + } + if (post.getVoteType() == CARD) { + currentDeadLine = post.getCardPoll().getDeadline(); + long daysUntilDeadline = ChronoUnit.DAYS.between(currentDeadLine, request.getDeadline()); + if (request.getDeadline().isBefore(LocalDateTime.now())) { + throw new GeneralException(DEADLINE_LIMIT); + } + if (!(daysUntilDeadline <= 30)){ + throw new GeneralException(DEADLINE_LIMIT); + } + post.getCardPoll().setDeadline(request.getDeadline()); + } + if (post.getVoteType() == GAUGE) { + currentDeadLine = post.getGaugePoll().getDeadline(); + long daysUntilDeadline = ChronoUnit.DAYS.between(currentDeadLine, request.getDeadline()); + if (request.getDeadline().isBefore(LocalDateTime.now())) { + throw new GeneralException(DEADLINE_LIMIT); + } + if (!(daysUntilDeadline <= 30)) { + throw new GeneralException(DEADLINE_LIMIT); + } + post.getGaugePoll().setDeadline(request.getDeadline()); + } + } + if(!request.getVoteOnGoing()){ + if (post.getVoteType() == GENERAL) { + post.getGeneralPoll().setVoteOnGoing(false); + } + if (post.getVoteType() == CARD) { + post.getCardPoll().setVoteOnGoing(false); + } + if (post.getVoteType() == GAUGE) { + post.getGaugePoll().setVoteOnGoing(false); + } } post.setTitle(request.getTitle()); post.setContent(request.getContent()); - + post.setIsFixed(post.getIsFixed()+1); } @Override diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index 92946bb..e028685 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -1,5 +1,7 @@ package friend.spring.service; +import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.converter.VoteConverter; import friend.spring.domain.*; import friend.spring.repository.*; @@ -27,11 +29,11 @@ public class VoteServiceImpl implements VoteService{ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long PostId, Long userId) { General_vote newGeneralVote = VoteConverter.toGeneralVote(request); User user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("\"" + userId + "\"해당 유저가 없습니다")); + .orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); newGeneralVote.setUser(user); Post post=postRepository.findById(PostId) - .orElseThrow(()-> new RuntimeException("\"" + PostId + "\"해당 글이 없습니다")); + .orElseThrow(()-> new GeneralException(ErrorStatus.POST_NOT_FOUND)); General_poll generalPoll=post.getGeneralPoll(); newGeneralVote.setGeneralPoll(generalPoll); @@ -42,7 +44,7 @@ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request .collect(Collectors.toList()); for (Long selectedId : selectedCandidateIds) { if (!validCandidateIds.contains(selectedId)) { - throw new RuntimeException("해당 후보 ID가 존재하지 않습니다: " + selectedId); + throw new GeneralException(ErrorStatus.CANDIDATE_NOT_FOUND); } } @@ -66,11 +68,11 @@ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long PostId, Long userId){ Gauge_vote newGaugeVote = VoteConverter.toGaugeVote(request); User user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("\"" + userId + "\"해당 유저가 없습니다")); + .orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); newGaugeVote.setUser(user); Post post=postRepository.findById(PostId) - .orElseThrow(()-> new RuntimeException("\"" + PostId + "\"해당 글이 없습니다")); + .orElseThrow(()-> new GeneralException(ErrorStatus.POST_NOT_FOUND)); Gauge_poll gaugePoll=post.getGaugePoll(); newGaugeVote.setGaugePoll(gaugePoll); @@ -99,11 +101,11 @@ public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request,Long PostId, Long userId){ Card_vote newCardVote = VoteConverter.toCardVote(request); User user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("\"" + userId + "\"해당 유저가 없습니다")); + .orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); newCardVote.setUser(user); Post post=postRepository.findById(PostId) - .orElseThrow(()-> new RuntimeException("\"" + PostId + "\"해당 글이 없습니다")); + .orElseThrow(()-> new GeneralException(ErrorStatus.POST_NOT_FOUND)); Card_poll cardPoll=post.getCardPoll(); newCardVote.setCardPoll(cardPoll); @@ -114,7 +116,7 @@ public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request,Long Pos .collect(Collectors.toList()); for (Long selectedId : selectedCandidateIds) { if (!validCandidateIds.contains(selectedId)) { - throw new RuntimeException("해당 후보 ID가 존재하지 않습니다: " + selectedId); + throw new GeneralException(ErrorStatus.CANDIDATE_NOT_FOUND); } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 2a11fca..d130a55 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; import java.util.List; @RestController @@ -44,7 +45,7 @@ public class CommentRestController { }) public ApiResponse createComment( @PathVariable("post-id") Long postId, - @RequestBody CommentRequestDTO.commentCreateReq requestBody, + @RequestBody @Valid CommentRequestDTO.commentCreateReq requestBody, @RequestHeader(name = "atk") String atk, HttpServletRequest request ) { diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index a77dcac..02d2c29 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -105,15 +105,14 @@ public ApiResponse getPostDetail(@PathVariab @RequestHeader("atk") String atk, HttpServletRequest request2){ Long userId=jwtTokenService.JwtToId(request2); - Optional postOptional =postQueryService.getPostDetail(PostId); + Post post =postQueryService.getPostDetail(PostId); Post parentPost=postQueryService.ParentPost(PostId);; Boolean engage=postQueryService.checkEngage(PostId,userId); - Post post = postOptional.get(); return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage,userId,parentPost)); } @GetMapping("/poll-post/{category}") - @Operation(summary = "고민글 전체 보기 API", description = "글 전체 보기합니다") + @Operation(summary = "고민글 전체 보기 API", description = "고민글 전체 보기합니다") @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)"), @@ -132,7 +131,7 @@ public ApiResponse getPostDetail(@RequestPar } @GetMapping("/review-post") - @Operation(summary = "후기글 전체 보기 API", description = "글 전체 보기합니다") + @Operation(summary = "후기글 전체 보기 API", description = "후기글 전체 보기합니다") @Parameters({ @Parameter(name = "arrange", description = "query string(RequestParam) - 정렬 기준 변수입니다. (0: 조회순,1: 최신순) 디폴트값 0"), @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작) 디폴트값 0"), @@ -156,7 +155,7 @@ public ApiResponse getReviewDetail(@Reques @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) public ApiResponse editPost(@PathVariable("post-id") Long postId, - @RequestBody PostRequestDTO.PostEditReq request, + @RequestBody @Valid PostRequestDTO.PostEditReq request, @RequestHeader("atk") String atk, HttpServletRequest request2) { Long userId=jwtTokenService.JwtToId(request2); diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index c5e6304..e51391c 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -181,7 +181,7 @@ public ApiResponse logout(@RequestHeader(name = "atk") String atk, HttpS } @GetMapping("/point") - @Operation(summary = "포인트 조회 API", description = "임시로 user-id 입력") + @Operation(summary = "포인트 조회 API", description = "유저의 포인트 내역을 조회하는 API입니다") public ApiResponse myPoint(@RequestHeader("atk") String atk, HttpServletRequest request2) { diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index fa99c7e..7b32508 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -3,33 +3,39 @@ import friend.spring.domain.Category; import friend.spring.domain.Post; +import friend.spring.validation.annotation.ContentTextLimit; +import friend.spring.validation.annotation.DeadlineLimit; +import friend.spring.validation.annotation.TitleTextLimit; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import net.bytebuddy.asm.Advice; import org.apache.tomcat.jni.Poll; import org.springframework.web.multipart.MultipartFile; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; import java.sql.Timestamp; +import java.time.LocalDateTime; import java.util.List; public class PostRequestDTO { @Getter public static class AddPostDTO{ - @NotBlank + @TitleTextLimit String title; - @NotBlank + @ContentTextLimit String content; String category; - @NotBlank + @NotNull Integer postType; // 1: vote, 2: review Integer postVoteType;// 1: general, 2: gauge String pollTitle; Boolean multipleChoice; Long parent_id; - @NotBlank - Timestamp deadline; + @DeadlineLimit + LocalDateTime deadline; Integer point; } @Getter @@ -42,10 +48,12 @@ public static class ReviewPostGetDTO{ @NoArgsConstructor @AllArgsConstructor public static class PostEditReq { - @NotBlank + @TitleTextLimit String title; - @NotBlank + @ContentTextLimit String content; + LocalDateTime deadline; + Boolean voteOnGoing; } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index c95cfa4..7952d6b 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -1,4 +1,5 @@ package friend.spring.web.dto; +import friend.spring.validation.annotation.TitleTextLimit; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -28,13 +29,15 @@ public static class PostDetailResponse { LocalDateTime createdAt; String title; String content; + Boolean OnGoing; + Boolean isVoted; //투표글에서만 사용, 후기글에서는 null List file; // 첨부파일 이미지 리스트 String pollTitle; // 투표글에서만 사용, 후기글에서는 null List pollOption; // 투표글에서만 사용, 후기글에서는 null Integer gauge; // 게이지 투표글에서만 사용, 후기글에서는 null Integer point; // 투표글에서만 사용, 후기글에서는 null ParentPostDTO parentPost; // 후기글에서만 사용, 일반글에서는 null - Timestamp deadline; // 투표글에서만 사용, 후기글에서는 null + LocalDateTime deadline; // 투표글에서만 사용, 후기글에서는 null List userVote; // 투표글에서 사용자가 투표완료시 투표한 후보 List percent; // 투표글에서 사용자가 투표 완료시 투표한 후보 선택 퍼센트 List voteResult; // 투표글에서 사용자가 투표 완료시 투표인원/총인원 From 6c879a96c7ad56c31cd86f8856053dcb544f61ce Mon Sep 17 00:00:00 2001 From: hjh Date: Sat, 10 Feb 2024 04:52:07 +0900 Subject: [PATCH 153/255] =?UTF-8?q?#95=20Feat:=20=EC=A0=9C=EC=95=BD?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=20=EC=84=A4=EC=A0=95,=20=EC=9E=90=EC=8B=A0?= =?UTF-8?q?=EC=9D=B4=20=EC=93=B4=20=EA=B8=80=20=EC=83=81=EC=84=B8=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=EC=8B=9C=201=EB=93=B1=20=ED=9B=84=EB=B3=B4=EB=A7=8C?= =?UTF-8?q?=20=EB=82=98=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95,?= =?UTF-8?q?=20=ED=88=AC=ED=91=9C=20=EC=97=AC=EB=B6=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../annotation/ContentTextLimit.java | 17 ++++++++++ .../validation/annotation/DeadlineLimit.java | 19 ++++++++++++ .../validation/annotation/TitleTextLimit.java | 17 ++++++++++ .../validator/ContentTextLimitValidator.java | 30 ++++++++++++++++++ .../validator/DeadlineLimitValidator.java | 31 +++++++++++++++++++ .../validator/TitleTextLimitValidator.java | 30 ++++++++++++++++++ 6 files changed, 144 insertions(+) create mode 100644 src/main/java/friend/spring/validation/annotation/ContentTextLimit.java create mode 100644 src/main/java/friend/spring/validation/annotation/DeadlineLimit.java create mode 100644 src/main/java/friend/spring/validation/annotation/TitleTextLimit.java create mode 100644 src/main/java/friend/spring/validation/validator/ContentTextLimitValidator.java create mode 100644 src/main/java/friend/spring/validation/validator/DeadlineLimitValidator.java create mode 100644 src/main/java/friend/spring/validation/validator/TitleTextLimitValidator.java diff --git a/src/main/java/friend/spring/validation/annotation/ContentTextLimit.java b/src/main/java/friend/spring/validation/annotation/ContentTextLimit.java new file mode 100644 index 0000000..1eb36e2 --- /dev/null +++ b/src/main/java/friend/spring/validation/annotation/ContentTextLimit.java @@ -0,0 +1,17 @@ +package friend.spring.validation.annotation; + +import friend.spring.validation.validator.ContentTextLimitValidator; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = ContentTextLimitValidator.class) +@Target( { ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ContentTextLimit { + String message() default "최소 5자 이상, 1000자 미만 입력해 주세요."; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/src/main/java/friend/spring/validation/annotation/DeadlineLimit.java b/src/main/java/friend/spring/validation/annotation/DeadlineLimit.java new file mode 100644 index 0000000..9264f2c --- /dev/null +++ b/src/main/java/friend/spring/validation/annotation/DeadlineLimit.java @@ -0,0 +1,19 @@ +package friend.spring.validation.annotation; + +import friend.spring.validation.validator.DeadlineLimitValidator; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = DeadlineLimitValidator.class) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface DeadlineLimit { + String message() default "Deadline must be between 1 minute and 30 days from now."; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/src/main/java/friend/spring/validation/annotation/TitleTextLimit.java b/src/main/java/friend/spring/validation/annotation/TitleTextLimit.java new file mode 100644 index 0000000..6065ff1 --- /dev/null +++ b/src/main/java/friend/spring/validation/annotation/TitleTextLimit.java @@ -0,0 +1,17 @@ +package friend.spring.validation.annotation; + +import friend.spring.validation.validator.TitleTextLimitValidator; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = TitleTextLimitValidator.class) +@Target( { ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +public @interface TitleTextLimit { + String message() default "최소 5자 이상, 30자 미만 입력해 주세요."; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/src/main/java/friend/spring/validation/validator/ContentTextLimitValidator.java b/src/main/java/friend/spring/validation/validator/ContentTextLimitValidator.java new file mode 100644 index 0000000..44a2515 --- /dev/null +++ b/src/main/java/friend/spring/validation/validator/ContentTextLimitValidator.java @@ -0,0 +1,30 @@ +package friend.spring.validation.validator; + +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.validation.annotation.ContentTextLimit; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +@Component +@RequiredArgsConstructor +public class ContentTextLimitValidator implements ConstraintValidator { + @Override + public void initialize(ContentTextLimit constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + boolean isValid= value.length() >= 5 && value.length() < 1000; + if(!isValid){ + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.CONTENT_TEXT_LIMIT.getMessage()).addConstraintViolation(); + } + + return isValid; + } + +} diff --git a/src/main/java/friend/spring/validation/validator/DeadlineLimitValidator.java b/src/main/java/friend/spring/validation/validator/DeadlineLimitValidator.java new file mode 100644 index 0000000..cdc00e5 --- /dev/null +++ b/src/main/java/friend/spring/validation/validator/DeadlineLimitValidator.java @@ -0,0 +1,31 @@ +package friend.spring.validation.validator; + +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.validation.annotation.DeadlineLimit; + + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; + +public class DeadlineLimitValidator implements ConstraintValidator { + + @Override + public boolean isValid(LocalDateTime deadline, ConstraintValidatorContext context) { + if (deadline == null) { + return true; + } + + LocalDateTime now = LocalDateTime.now(); + long minutesUntilDeadline = ChronoUnit.MINUTES.between(now, deadline); + long daysUntilDeadline = ChronoUnit.DAYS.between(now, deadline); + + boolean isValid = minutesUntilDeadline >= 1 && daysUntilDeadline <= 30; + if(!isValid){ + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.DEADLINE_LIMIT.getMessage()).addConstraintViolation(); + } + return isValid; + } +} diff --git a/src/main/java/friend/spring/validation/validator/TitleTextLimitValidator.java b/src/main/java/friend/spring/validation/validator/TitleTextLimitValidator.java new file mode 100644 index 0000000..d4ab8ab --- /dev/null +++ b/src/main/java/friend/spring/validation/validator/TitleTextLimitValidator.java @@ -0,0 +1,30 @@ +package friend.spring.validation.validator; + +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.validation.annotation.TitleTextLimit; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +@Component +@RequiredArgsConstructor +public class TitleTextLimitValidator implements ConstraintValidator { + + @Override + public void initialize(TitleTextLimit constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + boolean isValid= value.length() >= 5 && value.length() < 30; + if(!isValid){ + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(ErrorStatus.TITLE_TEXT_LIMIT.getMessage()).addConstraintViolation(); + } + + return isValid; + } +} From 717337cabdee90efb746167604dcbdccd8853974 Mon Sep 17 00:00:00 2001 From: hjh Date: Sat, 10 Feb 2024 05:15:30 +0900 Subject: [PATCH 154/255] =?UTF-8?q?#95=20Feat:=20=EC=9D=BC=EB=B0=98?= =?UTF-8?q?=ED=88=AC=ED=91=9C=20=EC=83=81=EC=84=B8=EB=B3=B4=EA=B8=B0=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/PostConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index ea13be7..eca7205 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -336,7 +336,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .collect(Collectors.toList()); // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 - userChoiceList = post.getCardPoll().getCandidateList().stream() + userChoiceList = post.getGeneralPoll().getCandidateList().stream() .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) .map(PostConverter::toPollOptionResDTO) .collect(Collectors.toList()); From 2f0f4ef3899ec644b98546b5e4b51eafa4529a93 Mon Sep 17 00:00:00 2001 From: hjh Date: Sat, 10 Feb 2024 05:20:35 +0900 Subject: [PATCH 155/255] =?UTF-8?q?#95=20Feat:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=95=B8=EB=93=A4=EB=9F=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 1 + .../friend/spring/service/PostServiceImpl.java | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 708aee0..28aae9f 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -43,6 +43,7 @@ public enum ErrorStatus implements BaseErrorCode { DEADLINE_LIMIT(HttpStatus.BAD_REQUEST,"POST4010","최소 1분~최대30일로 입력해 주세요"), CANDIDATE_NOT_FOUND(HttpStatus.NOT_FOUND,"POST4011","후보를 찾을 수 없습니다"), TOO_MUCH_FIXED(HttpStatus.NOT_FOUND,"POST4012","이미 2회 이상 수정 했습니다"), + NOT_ENOUGH_POINT(HttpStatus.BAD_REQUEST,"POST4013","해당 유저의 포인트가 부족 합니다"), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index ab3ebc9..eab0193 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -121,7 +121,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque //포인트 차감 관련 코드 if(request.getPoint()!=null) { if (!checkPoint(request, user)) { - throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); + throw new GeneralException(NOT_ENOUGH_POINT); } user.setPoint(user.getPoint() - request.getPoint()); Point newPoint=Point.builder() @@ -148,7 +148,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque //포인트 차감 관련 코드 if(request.getPoint()!=null) { if (!checkPoint(request, user)) { - throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); + throw new GeneralException(NOT_ENOUGH_POINT); } user.setPoint(user.getPoint() - request.getPoint()); Point newPoint=Point.builder() @@ -160,7 +160,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque } if(!checkPoint(request, user)&&request.getPoint()!=null){ - throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); + throw new GeneralException(NOT_ENOUGH_POINT); } Card_poll cardPoll = Card_poll.builder() @@ -178,7 +178,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque //포인트 차감 관련 코드 if(request.getPoint()!=null) { if (!checkPoint(request, user)) { - throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); + throw new GeneralException(NOT_ENOUGH_POINT); } user.setPoint(user.getPoint() - request.getPoint()); Point newPoint=Point.builder() @@ -190,7 +190,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque } if(!checkPoint(request, user)&&request.getPoint()!=null){ - throw new RuntimeException("\""+userId+"\"해당 유저의 포인트가 부족 합니다"); + throw new GeneralException(NOT_ENOUGH_POINT); } Gauge_poll gaugePoll = Gauge_poll.builder() @@ -205,9 +205,9 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque if(newPost.getPostType()==REVIEW&&request.getParent_id()!=null){ Post parent=postRepository.findById(request.getParent_id()) - .orElseThrow(()->new RuntimeException("\""+request.getParent_id()+"\"해당 글이 없습니다")); + .orElseThrow(()->new GeneralException(POST_NOT_FOUND)); if(!userId.equals(parent.getUser().getId())){ - throw new RuntimeException("타 유저 글입니다. 후기글 작성 권한이 없습니다."); + throw new GeneralException(POST_NOT_CORRECT_USER); } newPost.setParentPost(parent); } @@ -325,7 +325,7 @@ public void deletePost(Long postId, Long userId) { User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); if(!user.getId().equals(post.getUser().getId())){ - throw new RuntimeException("삭제 권환이 없습니다 글이 없습니다"); + throw new GeneralException(POST_NOT_CORRECT_USER); } post.setStateDel(); } From 9423eaa5859508cd758de36840525dcfd0641944 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 10 Feb 2024 07:22:17 +0900 Subject: [PATCH 156/255] =?UTF-8?q?#95=20Refactor:=20Timezone=20=EC=84=9C?= =?UTF-8?q?=EC=9A=B8=20=EC=8B=9C=EA=B0=84=EB=8C=80=EB=A1=9C=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/Application.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/friend/spring/Application.java b/src/main/java/friend/spring/Application.java index 401acbc..472f691 100644 --- a/src/main/java/friend/spring/Application.java +++ b/src/main/java/friend/spring/Application.java @@ -4,12 +4,22 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import javax.annotation.PostConstruct; +import java.time.LocalDateTime; +import java.util.TimeZone; + @SpringBootApplication @EnableJpaAuditing public class Application { + @PostConstruct + public void started() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")); + } + public static void main(String[] args) { SpringApplication.run(Application.class, args); + System.out.println("현재시간 " + LocalDateTime.now()); } } From 694ffb6e9955d079fdf119bb7bdcdf81f4ea04a5 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Sat, 10 Feb 2024 12:31:57 +0900 Subject: [PATCH 157/255] =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/apiPayload/code/status/ErrorStatus.java | 9 +++++++++ .../java/friend/spring/security/JwtTokenProvider.java | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 0163d9c..004b228 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -28,6 +28,15 @@ public enum ErrorStatus implements BaseErrorCode { INVALID_JWT(HttpStatus.UNAUTHORIZED, "USER4007", "유효하지 않은 JWT입니다."), PASSWORD_INCORRECT(HttpStatus.NOT_FOUND, "USER4008", "비밀번호가 틀렸습니다."), RTK_INCORREXT(HttpStatus.UNAUTHORIZED,"USER4100","RefreshToken값을 확인해주세요."), + + // Auth 관련 + AUTH_EXPIRED_TOKEN(HttpStatus.UNAUTHORIZED, "AUTH_4101", "토큰이 만료되었습니다."), + AUTH_INVALID_TOKEN(HttpStatus.UNAUTHORIZED, "AUTH_4102", "토큰이 유효하지 않습니다."), + INVALID_LOGIN_REQUEST(HttpStatus.UNAUTHORIZED, "AUTH_4103", "올바른 이메일이나 패스워드가 아닙니다."), + INVALID_REQUEST_INFO(HttpStatus.UNAUTHORIZED, "AUTH_4106", "카카오 정보 불러오기에 실패하였습니다."), + NOT_EQUAL_TOKEN(HttpStatus.UNAUTHORIZED, "AUTH_4107", "리프레시 토큰이 다릅니다."), + NOT_CONTAIN_TOKEN(HttpStatus.UNAUTHORIZED, "AUTH_4108", "해당하는 토큰이 저장되어있지 않습니다."), + // 글 관련 응답 POST_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4001", "글을 찾을 수 없습니다."), POST_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "POST4002", "올바른 사용자(글 작성자)가 아닙니다."), diff --git a/src/main/java/friend/spring/security/JwtTokenProvider.java b/src/main/java/friend/spring/security/JwtTokenProvider.java index 186ed6b..12880b2 100644 --- a/src/main/java/friend/spring/security/JwtTokenProvider.java +++ b/src/main/java/friend/spring/security/JwtTokenProvider.java @@ -54,7 +54,7 @@ protected void init() { // JWT Access 토큰 생성 public TokenDTO createAccessToken(String email) { // 토큰 유효시간 30분 - long tokenValidTime = 30 * 60 * 1000L; + long tokenValidTime =2 * 60 * 60 * 1000L; Optional user = userRepository.findByEmail(email); @@ -81,7 +81,7 @@ public TokenDTO createAccessToken(String email) { // JWT Refresh 토큰 생성 public TokenDTO createRefreshToken(String email) { // Refresh 토큰 유효시간 2주 - long tokenValidTime = 30 * 60 * 1000L; + long tokenValidTime = 2 * 7 * 24 * 60 * 60 * 1000L; Optional user = userRepository.findByEmail(email); Claims claims = Jwts.claims().setSubject(email); // JWT payload에 저장되는 정보단위 From 58c5e5acc0e79ff4e685cabb13381278902bac5c Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 10 Feb 2024 23:29:59 +0900 Subject: [PATCH 158/255] =?UTF-8?q?#33=20Refactor:=20=EA=B8=80=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20=EC=A4=91=EB=B3=B5=20=EB=B6=88=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/apiPayload/code/status/ErrorStatus.java | 1 + src/main/java/friend/spring/service/PostServiceImpl.java | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 9e4eb6d..836f1b9 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -46,6 +46,7 @@ public enum ErrorStatus implements BaseErrorCode { POST_SCRAP_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4004", "글에 대한 스크랩 데이터를 찾을 수 없습니다."), POST_GENERAL_POLL_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4005", "글에 대한 일반 투표 데이터를 찾을 수 없습니다."), POST_CARD_POLL_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4006", "글에 대한 카드 투표 데이터를 찾을 수 없습니다."), + POST_LIKE_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4007", "글에 대한 좋아요 데이터가 이미 존재합니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 07e34d8..7e2ed74 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -82,6 +82,8 @@ public Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user) { public void checkPostLike(Boolean flag) { if (!flag) { throw new PostHandler(POST_LIKE_NOT_FOUND); + } else { + throw new PostHandler(POST_LIKE_DUPLICATE); } } @@ -307,6 +309,11 @@ public Post_like likePost(Long postId, HttpServletRequest request) { User user = optionalUser.get(); Post_like post_like = PostConverter.toPostLike(post, user); + Optional optionalPost_like = postLikeRepository.findByPostIdAndUserId(postId, userId); + if (!optionalPost_like.isEmpty()) { + this.checkPostLike(true); + } + return postLikeRepository.save(post_like); } From 36d89bfec7fd782b4d704368abeabfe0bbbd3b38 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 10 Feb 2024 23:38:35 +0900 Subject: [PATCH 159/255] =?UTF-8?q?#33=20Refactor:=20=EA=B8=80=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=9E=A9=20=EC=A4=91=EB=B3=B5=20=EB=B6=88=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/apiPayload/code/status/ErrorStatus.java | 1 + src/main/java/friend/spring/service/PostServiceImpl.java | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 836f1b9..7290f1f 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -47,6 +47,7 @@ public enum ErrorStatus implements BaseErrorCode { POST_GENERAL_POLL_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4005", "글에 대한 일반 투표 데이터를 찾을 수 없습니다."), POST_CARD_POLL_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4006", "글에 대한 카드 투표 데이터를 찾을 수 없습니다."), POST_LIKE_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4007", "글에 대한 좋아요 데이터가 이미 존재합니다."), + POST_SCRAP_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4008", "글에 대한 스크랩 데이터가 이미 존재합니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 7e2ed74..8de8728 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -91,6 +91,8 @@ public void checkPostLike(Boolean flag) { public void checkPostScrap(Boolean flag) { if (!flag) { throw new PostHandler(POST_SCRAP_NOT_FOUND); + } else { + throw new PostHandler(POST_SCRAP_DUPLICATE); } } @@ -444,6 +446,10 @@ public Post_scrap createScrapPost(Long postId, HttpServletRequest request) { User user = optionalUser.get(); Post_scrap post_scrap = PostConverter.toPostScrap(post, user); + Optional optionalPost_scrap = postScrapRepository.findByPostIdAndUserId(postId, userId); + if (!optionalPost_scrap.isEmpty()) { + this.checkPostScrap(true); + } return postScrapRepository.save(post_scrap); } From 7535bd906a5d77d5be56daffb5b6c17aa4194ec3 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 11 Feb 2024 01:12:19 +0900 Subject: [PATCH 160/255] =?UTF-8?q?#30=20Refactor:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=B1=84=ED=83=9D=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=82=B4=EC=9A=A9=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20=EA=B8=80/=EB=8C=93=EA=B8=80=20=EC=86=8C=EC=86=8D=20?= =?UTF-8?q?=EC=9D=BC=EC=B9=98=20=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/service/CommentServiceImpl.java | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 69b6e62..6bb6059 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -5,6 +5,7 @@ import friend.spring.apiPayload.handler.CommentHandler; import friend.spring.converter.CommentConverter; import friend.spring.domain.Comment; +import friend.spring.domain.Point; import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.mapping.Comment_choice; @@ -37,6 +38,7 @@ public class CommentServiceImpl implements CommentService { private final UserRepository userRepository; private final CommentLikeRepository commentLikeRepository; private final CommentChoiceRepository commentChoiceRepository; + private final PointRepository pointRepository; private final UserService userService; private final PostService postService; private final JwtTokenProvider jwtTokenProvider; @@ -135,6 +137,7 @@ public Comment_like likeComment(Long postId, Long commentId, HttpServletRequest Comment comment = optionalComment.get(); User user = optionalUser.get(); + // 댓글 소속이 글과 일치하는지 확인 if (!Objects.equals(comment.getPost().getId(), post.getId())) { throw new CommentHandler(COMMENT_POST_NOT_MATCH); } @@ -183,6 +186,11 @@ public void dislikeComment(Long postId, Long commentId, HttpServletRequest reque this.checkComment(false); } + // 댓글 소속이 글과 일치하는지 확인 + if (!Objects.equals(optionalComment.get().getPost().getId(), optionalPost.get().getId())) { + throw new CommentHandler(COMMENT_POST_NOT_MATCH); + } + Optional optionalUser = userRepository.findById(userId); if (optionalUser.isEmpty()) { userService.checkUser(false); @@ -211,6 +219,11 @@ public Comment_choice selectComment(Long postId, Long commentId, HttpServletRequ this.checkComment(false); } + // 댓글 소속이 글과 일치하는지 확인 + if (!Objects.equals(optionalComment.get().getPost().getId(), optionalPost.get().getId())) { + throw new CommentHandler(COMMENT_POST_NOT_MATCH); + } + Optional optionalUser = userRepository.findById(userId); // 이 사용자가 존재하는지 확인 if (optionalUser.isEmpty()) { @@ -238,6 +251,16 @@ public Comment_choice selectComment(Long postId, Long commentId, HttpServletRequ } Comment_choice comment_choice = CommentConverter.toCommentChoice(post, comment); + + // 채택된 사용자에게 포인트 적립 + comment.getUser().setPoint(comment.getUser().getPoint() + post.getPoint()); + Point newPoint = Point.builder() + .amount(post.getPoint()) + .content("채택된 댓글에 대한 " + post.getPoint() + " 포인트 적립") + .build(); + newPoint.setUser(user); + pointRepository.save(newPoint); + return commentChoiceRepository.save(comment_choice); } @@ -247,8 +270,14 @@ public void editComment(Long postId, Long commentId, CommentRequestDTO.commentEd Long userId = jwtTokenProvider.getCurrentUser(request); User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); - postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + Post post = postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); Comment comment = commentRepository.findById(commentId).orElseThrow(() -> new GeneralException(ErrorStatus.COMMENT_NOT_FOUND)); + + // 댓글 소속이 글과 일치하는지 확인 + if (!Objects.equals(comment.getPost().getId(), post.getId())) { + throw new CommentHandler(COMMENT_POST_NOT_MATCH); + } + // 로그인한 사용자가 이 댓글의 작성자인지 확인 if (!Objects.equals(user.getId(), comment.getUser().getId())) { // 작성자가 아닌 경우 -> 에러 반환 @@ -275,8 +304,14 @@ public void deleteComment(Long postId, Long commentId, HttpServletRequest reques Long userId = jwtTokenProvider.getCurrentUser(request); User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); - postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + Post post = postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); Comment comment = commentRepository.findById(commentId).orElseThrow(() -> new GeneralException(ErrorStatus.COMMENT_NOT_FOUND)); + + // 댓글 소속이 글과 일치하는지 확인 + if (!Objects.equals(comment.getPost().getId(), post.getId())) { + throw new CommentHandler(COMMENT_POST_NOT_MATCH); + } + // 로그인한 사용자가 이 댓글의 작성자인지 확인 if (!Objects.equals(user.getId(), comment.getUser().getId())) { // 작성자가 아닌 경우 -> 에러 반환 From 0ff5087ac5bc9e81451519eb4baf4fcd4df5a201 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 11 Feb 2024 01:25:48 +0900 Subject: [PATCH 161/255] =?UTF-8?q?#29=20Refactor:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20page=20=EC=B2=98=EB=A6=AC=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/repository/CommentRepository.java | 2 +- .../friend/spring/service/CommentService.java | 2 +- .../spring/service/CommentServiceImpl.java | 20 ++++++++----------- .../web/controller/CommentRestController.java | 13 ++++-------- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/main/java/friend/spring/repository/CommentRepository.java b/src/main/java/friend/spring/repository/CommentRepository.java index a0a3d31..96c8a1c 100644 --- a/src/main/java/friend/spring/repository/CommentRepository.java +++ b/src/main/java/friend/spring/repository/CommentRepository.java @@ -10,7 +10,7 @@ import java.util.List; public interface CommentRepository extends JpaRepository { - Page findByPostIdAndParentCommentIsNull(Long postId, Pageable pageable); + List findByPostIdAndParentCommentIsNull(Long postId); Page findAllByUser(User user, PageRequest pageRequest); diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index 808de43..8aea81d 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -21,7 +21,7 @@ public interface CommentService { Comment_like likeComment(Long postId, Long commentId, HttpServletRequest request); - Page getComments(Long postId, Integer page, Integer size); + List getComments(Long postId); void dislikeComment(Long postId, Long commentId, HttpServletRequest request); diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 6bb6059..5086516 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -152,24 +152,20 @@ public Comment_like likeComment(Long postId, Long commentId, HttpServletRequest } @Override - public Page getComments(Long postId, Integer page, Integer size) { + public List getComments(Long postId) { Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { postService.checkPost(false); } - Pageable pageable = PageRequest.of(page, size); - Page commentPage = commentRepository.findByPostIdAndParentCommentIsNull(postId, pageable); // 루트 댓글만 가져옴 - List commentGetResList = commentPage - .map(comment -> { - CommentResponseDTO.commentGetRes commentGetRes = CommentConverter.toCommentGetRes(comment); - return commentGetRes; - }) - .filter(Objects::nonNull) // null인 요소는 필터링 - .get() - .collect(Collectors.toList()); + List commentList = commentRepository.findByPostIdAndParentCommentIsNull(postId); // 루트 댓글만 가져옴 + List commentGetResList = new ArrayList<>(); + for (Comment comment : commentList) { + CommentResponseDTO.commentGetRes commentGetRes = CommentConverter.toCommentGetRes(comment); + commentGetResList.add(commentGetRes); + } - return new PageImpl<>(commentGetResList, pageable, commentPage.getTotalElements()); + return commentGetResList; } @Override diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 2a11fca..ef9bde9 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -109,17 +109,12 @@ public ApiResponse dislikeComment( @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), }) @Parameters({ - @Parameter(name = "post-id", description = "path variable - 글 아이디"), - @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), - @Parameter(name = "size", description = "query string(RequestParam) - 루트댓글 몇 개씩 불러올지 개수를 세는 변수 (1 이상 자연수로 설정)") + @Parameter(name = "post-id", description = "path variable - 글 아이디") }) - public ApiResponse> getComments( - @PathVariable("post-id") Long postId, - @RequestParam(name = "page") Integer page, - @RequestParam(name = "size") Integer size - + public ApiResponse> getComments( + @PathVariable("post-id") Long postId ) { - return ApiResponse.onSuccess(commentService.getComments(postId, page, size)); + return ApiResponse.onSuccess(commentService.getComments(postId)); } // 댓글 채택 From 0e74782bd1c5fed8b8d63fdb0072cacb4cabe197 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 11 Feb 2024 01:28:11 +0900 Subject: [PATCH 162/255] =?UTF-8?q?#29=20Chore:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20swagger=20=EC=84=A4=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/web/controller/CommentRestController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index ef9bde9..2295752 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -103,7 +103,7 @@ public ApiResponse dislikeComment( // 댓글 조회 @GetMapping("/{post-id}/comments") - @Operation(summary = "댓글 조회 API", description = "댓글을 조회하는 API입니다. ex) /posts/111/comments?page=0&size=10") + @Operation(summary = "댓글 조회 API", description = "댓글을 조회하는 API입니다. ex) /posts/111/comments") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), From f729eefe6d16d6714eb692b3c47c49919b7d5eca Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 11 Feb 2024 01:44:16 +0900 Subject: [PATCH 163/255] =?UTF-8?q?#55=20Chore:=20=ED=99=88=20-=20?= =?UTF-8?q?=EB=8B=B5=EB=B3=80=EC=9D=84=20=EA=B8=B0=EB=8B=A4=EB=A6=AC?= =?UTF-8?q?=EB=8A=94=20=EA=B3=A0=EB=AF=BC=EB=93=A4=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=8B=9C=20=EB=A6=AC=EB=B7=B0=20=EA=B8=80=20=EC=A0=9C=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/service/PostServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 07e34d8..ef33102 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -7,6 +7,7 @@ import friend.spring.converter.CandidateConverter; import friend.spring.converter.PostConverter; import friend.spring.domain.*; +import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.S3ImageType; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; @@ -362,7 +363,7 @@ public List getPostRes(Page postPage) List candidateList = null; List candidateSummaryResList = null; - if (post.getVoteType() == null) return null; // 고민 후기 글인 경우 패스 + if (post.getPostType().equals(REVIEW)) return null; // 고민 후기 글인 경우 패스 if (post.getVoteType().equals(GENERAL)) { // 일반 투표인 경우 postVoteType = "GENERAL"; From fa7ac2d00e04e5f33fa393d04bf53cc349afad22 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 11 Feb 2024 11:06:48 +0900 Subject: [PATCH 164/255] =?UTF-8?q?#55=20Feat:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95(=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=9E=90=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=82=AC=EC=A7=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/User.java | 4 ++++ .../friend/spring/service/MyPageService.java | 4 ++++ .../spring/service/MyPageServiceImpl.java | 23 +++++++++++++++++++ .../web/controller/MyPageRestController.java | 23 +++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 4c8fc3c..a1a8a35 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -161,5 +161,9 @@ public boolean isEnabled() { public void setPoint(Integer point) { this.point = point; } + + public void setFile(File file) { + this.file = file; + } } diff --git a/src/main/java/friend/spring/service/MyPageService.java b/src/main/java/friend/spring/service/MyPageService.java index 491cedf..c2ba280 100644 --- a/src/main/java/friend/spring/service/MyPageService.java +++ b/src/main/java/friend/spring/service/MyPageService.java @@ -4,7 +4,9 @@ import friend.spring.domain.Post; import friend.spring.domain.mapping.Post_scrap; import org.springframework.data.domain.Page; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.Optional; import java.util.Set; @@ -14,4 +16,6 @@ public interface MyPageService { List getCategoryList(Long userId); Page getAllPostList(Long userId, Integer page, Integer sort); + + void editUserImage(MultipartFile file, HttpServletRequest request); } diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index 21ed764..31f02af 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -5,13 +5,16 @@ import friend.spring.apiPayload.handler.PostHandler; import friend.spring.converter.MyPageConverter; import friend.spring.domain.Category; +import friend.spring.domain.File; import friend.spring.domain.Post; import friend.spring.domain.User; +import friend.spring.domain.enums.S3ImageType; import friend.spring.domain.mapping.Post_scrap; import friend.spring.repository.CategoryRepository; import friend.spring.repository.PostRepository; import friend.spring.repository.PostScrapRepository; import friend.spring.repository.UserRepository; +import friend.spring.security.JwtTokenProvider; import friend.spring.web.dto.MyPageResponseDTO; import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; @@ -22,7 +25,9 @@ import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletRequest; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -39,6 +44,9 @@ public class MyPageServiceImpl implements MyPageService{ private final PostRepository postRepository; private final CategoryRepository categoryRepository; private final PostScrapRepository postScrapRepository; + private final JwtTokenProvider jwtTokenProvider; + private final S3Service s3Service; + @Override public void checkPost(Boolean flag) { if (!flag) { @@ -71,4 +79,19 @@ else if (sort == 1){ } else return null; } + + @Override + @Transactional + public void editUserImage(MultipartFile file, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + User user = optionalUser.get(); + File newFile = s3Service.uploadSingleImage(file, S3ImageType.USER, user, null); + user.setFile(newFile); + } } diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index b2555dd..929b605 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -1,13 +1,16 @@ package friend.spring.web.controller; import friend.spring.apiPayload.ApiResponse; +import friend.spring.converter.CommentConverter; import friend.spring.converter.MyPageConverter; import friend.spring.domain.Category; import friend.spring.domain.Post; +import friend.spring.domain.mapping.Comment_choice; import friend.spring.service.JwtTokenService; import friend.spring.service.MyPageService; import friend.spring.service.PostService; import friend.spring.service.UserService; +import friend.spring.web.dto.CommentResponseDTO; import friend.spring.web.dto.MyPageResponseDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -15,7 +18,9 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.util.List; @@ -76,4 +81,22 @@ public ApiResponse getAllSavedPosts( return ApiResponse.onSuccess(MyPageConverter.toSavedAllPostResDTO(allPostList)); } + // 회원정보 수정(사용자 프로필 사진) + @PatchMapping(value = "/profile/modify/image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @Operation(summary = "회원정보 수정(사용자 프로필 사진) API", description = "회원정보 수정(사용자 프로필 사진)하는 API입니다. ex) /user/my-page/profile/modify/image") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) + public ApiResponse editUserImage( + @RequestParam("file") MultipartFile file, + @RequestHeader(name = "atk") String atk, + HttpServletRequest request + ) { + myPageService.editUserImage(file, request); + return ApiResponse.onSuccess(null); + } } From e1572affe73c3391b3dadc38fc9417bfad2b5d82 Mon Sep 17 00:00:00 2001 From: hjh Date: Sun, 11 Feb 2024 13:05:06 +0900 Subject: [PATCH 165/255] =?UTF-8?q?#102=20Feat:=20=EA=B8=80=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=EC=97=90=EC=84=9C=20=EA=B8=80=EC=93=B4=EC=9D=B4=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=82=AC=EC=A7=84=20=EB=B0=98?= =?UTF-8?q?=ED=99=98,=20=EB=82=B4=20=ED=88=AC=ED=91=9C=EB=B3=B4=EA=B8=B0?= =?UTF-8?q?=EC=8B=9C=20=EB=A7=88=EA=B0=90=EB=90=9C=20=ED=88=AC=ED=91=9C?= =?UTF-8?q?=EB=A7=8C=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 145 ++++++++++++++---- .../spring/service/PostQueryServiceImpl.java | 26 +++- .../web/controller/PostRestController.java | 8 +- .../friend/spring/web/dto/ParentPostDTO.java | 1 + .../spring/web/dto/PostResponseDTO.java | 5 + 5 files changed, 147 insertions(+), 38 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index eca7205..8d862a0 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -48,10 +48,19 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ ParentPollDTO parentPollDTO=null; Integer parentLikes =parentPost.getPostLikeList().size(); Integer parentComments= parentPost.getCommentList().size(); + File userFile=null; + String userImg=null; + Optional userFileOptional=Optional.ofNullable(parentPost.getUser().getFile()); + + if(userFileOptional.isPresent()){ + userFile = userFileOptional.get(); + userImg=userFile.getUrl(); + } if(parentPost.getVoteType()==PostVoteType.GAUGE) { return ParentPostDTO.builder() .nickname(parentPost.getUser().getNickname()) + .userImg(userImg) .title(parentPost.getTitle()) .content(parentPost.getContent()) .gauge(parentPost.getGaugePoll().getGauge()) @@ -91,22 +100,37 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ // 1등 후보의 정보를 ParentPollDTO 객체로 반환 if(highestSelectionCandidate.isPresent()) { parentPollDTO = highestSelectionCandidate.get(); - } - // 1등 후보 이름, 사진 반환 - Long id=parentPollDTO.getCandidateId(); - Optional name = parentPost.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> candidate.getId().equals(id)) - .map(Candidate::getName) - .findFirst(); - String candidateName=name.get(); - String candidateImage = parentPollDTO.getCandidateImage(); + // 1등 후보 이름, 사진 반환 + Long id=parentPollDTO.getCandidateId(); + //1등이 있는 경우만 포함. + Optional name = parentPost.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> candidate.getId().equals(id)) + .map(Candidate::getName) + .findFirst(); + String candidateName=name.get(); + String candidateImage = parentPollDTO.getCandidateImage(); - parentPollDTO.setCandidateName(candidateName); - parentPollDTO.setCandidateImage(candidateImage); + parentPollDTO.setCandidateName(candidateName); + parentPollDTO.setCandidateImage(candidateImage); + + } +// // 1등 후보 이름, 사진 반환 +// Long id=parentPollDTO.getCandidateId(); +// Optional name = parentPost.getGeneralPoll().getCandidateList().stream() +// .filter(candidate -> candidate.getId().equals(id)) +// .map(Candidate::getName) +// .findFirst(); +// String candidateName=name.get(); +// String candidateImage = parentPollDTO.getCandidateImage(); +// +// +// parentPollDTO.setCandidateName(candidateName); +// parentPollDTO.setCandidateImage(candidateImage); return ParentPostDTO.builder() .nickname(parentPost.getUser().getNickname()) + .userImg(userImg) .title(parentPost.getTitle()) .content(parentPost.getContent()) .pollOption(pollOptionDTOList) @@ -141,28 +165,48 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ // 선택률이 가장 높은 후보 찾기 Optional highestSelectionCandidate = candidateInfos.stream() .max(Comparator.comparingInt(ParentPollDTO::getRate)); + //1등이 있는 경우만 + if(highestSelectionCandidate.isPresent()) { + // 1등 후보의 정보를 ParentPollDTO 객체로 반환 + parentPollDTO = highestSelectionCandidate.get(); - // 1등 후보의 정보를 ParentPollDTO 객체로 반환 - parentPollDTO = highestSelectionCandidate.get(); - - // 1등 후보 이름, 사진 반환 - Long id=parentPollDTO.getCandidateId(); - Optional name = parentPost.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> candidate.getId().equals(id)) - .map(Candidate::getName) - .findFirst(); - String candidateName=name.get(); - Optional image = parentPost.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> candidate.getId().equals(id)) - .map(Candidate::getFile) - .findFirst(); - String candidateImage=image.get().getUrl(); - parentPollDTO.setCandidateName(candidateName); - parentPollDTO.setCandidateImage(candidateImage); + // 1등 후보 이름, 사진 반환 + Long id=parentPollDTO.getCandidateId(); + Optional name = parentPost.getCardPoll().getCandidateList().stream() + .filter(candidate -> candidate.getId().equals(id)) + .map(Candidate::getName) + .findFirst(); + String candidateName=name.get(); +// Optional image = parentPost.getCardPoll().getCandidateList().stream() +// .filter(candidate -> candidate.getId().equals(id)) +// .map(Candidate::getFile) +// .findFirst(); + String candidateImage=parentPollDTO.getCandidateImage(); + parentPollDTO.setCandidateName(candidateName); + parentPollDTO.setCandidateImage(candidateImage); + } +// // 1등 후보의 정보를 ParentPollDTO 객체로 반환 +// parentPollDTO = highestSelectionCandidate.get(); +// +// // 1등 후보 이름, 사진 반환 +// Long id=parentPollDTO.getCandidateId(); +// Optional name = parentPost.getGeneralPoll().getCandidateList().stream() +// .filter(candidate -> candidate.getId().equals(id)) +// .map(Candidate::getName) +// .findFirst(); +// String candidateName=name.get(); +// Optional image = parentPost.getGeneralPoll().getCandidateList().stream() +// .filter(candidate -> candidate.getId().equals(id)) +// .map(Candidate::getFile) +// .findFirst(); +// String candidateImage=image.get().getUrl(); +// parentPollDTO.setCandidateName(candidateName); +// parentPollDTO.setCandidateImage(candidateImage); return ParentPostDTO.builder() .nickname(parentPost.getUser().getNickname()) + .userImg(userImg) .title(parentPost.getTitle()) .content(parentPost.getContent()) .pollOption(pollOptionDTOList) @@ -234,11 +278,19 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B if(post.getUser().getId().equals(userId)){ myPost=true; } + File userFile=null; + String userImg=null; + Optional userFileOptional=Optional.ofNullable(post.getUser().getFile()); + if(userFileOptional.isPresent()){ + userFile = userFileOptional.get(); + userImg=userFile.getUrl(); + } if(post.getPostType()==REVIEW){ return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) + .userImg(userImg) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) @@ -259,6 +311,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B } return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) + .userImg(userImg) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) @@ -359,6 +412,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B } return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) + .userImg(userImg) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) @@ -491,6 +545,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B } return PostResponseDTO.PostDetailResponse.builder() .nickname(post.getUser().getNickname()) + .userImg(userImg) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) @@ -515,10 +570,21 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B //전체 보기 public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Long userId){ + File userFile=null; + String userImg=null; + Optional userFileOptional=Optional.ofNullable(post.getUser().getFile()); + + if(userFileOptional.isPresent()){ + userFile = userFileOptional.get(); + userImg=userFile.getUrl(); + } + //로컬 db test if(post.getPostType()==VOTE&&post.getVoteType()==null){ return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) .nickname(post.getUser().getNickname()) + .userImg(userImg) .content(Long.toString(post.getId())) .build(); } @@ -548,7 +614,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .collect(Collectors.toList()); return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) .nickname(post.getUser().getNickname()) + .userImg(userImg) .title(post.getTitle()) .content(post.getContent()) .uploadDate(post.getCreatedAt()) @@ -562,7 +630,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) .nickname(post.getUser().getNickname()) + .userImg(userImg) .title(post.getTitle()) .content(post.getContent()) .uploadDate(post.getCreatedAt()) @@ -579,7 +649,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } if(engage) { return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) .nickname(post.getUser().getNickname()) + .userImg(userImg) .title(post.getTitle()) .content(post.getContent()) .uploadDate(post.getCreatedAt()) @@ -591,7 +663,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .build(); } return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) .nickname(post.getUser().getNickname()) + .userImg(userImg) .title(post.getTitle()) .content(post.getContent()) .uploadDate(post.getCreatedAt()) @@ -603,7 +677,6 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - System.out.println("fuck"); if(!post.getCardPoll().getCardVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()){ engage=true; } @@ -619,7 +692,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .collect(Collectors.toList()); return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) .nickname(post.getUser().getNickname()) + .userImg(userImg) .title(post.getTitle()) .content(post.getContent()) .uploadDate(post.getCreatedAt()) @@ -633,7 +708,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) .nickname(post.getUser().getNickname()) + .userImg(userImg) .title(post.getTitle()) .content(post.getContent()) .uploadDate(post.getCreatedAt()) @@ -659,8 +736,18 @@ public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post p Integer commentCount = post.getCommentList().size(); Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + File userFile=null; + String userImg=null; + Optional userFileOptional=Optional.ofNullable(post.getUser().getFile()); + + if(userFileOptional.isPresent()){ + userFile = userFileOptional.get(); + userImg=userFile.getUrl(); + } return PostResponseDTO.ReviewPostGetResponse.builder() + .postId(post.getId()) .nickname(post.getUser().getNickname()) + .userImg(userImg) .title(post.getTitle()) .content(post.getContent()) .ReviewPicList(FileConverter.toFileDTO(post.getFileList())) diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index fcd20dd..539d7c6 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -12,16 +12,14 @@ import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; +import org.springframework.data.domain.*; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityNotFoundException; import javax.servlet.http.HttpServletRequest; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -122,7 +120,25 @@ public Page getParentPostList(Integer page, Integer size, HttpServletReque Long userId = jwtTokenProvider.getCurrentUser(request); Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); // List userPost = postRepository.findByUserId(userId); - return postRepository.findByUserIdAndPostTypeAndState(userId, PostType.VOTE, PostState.POSTING, pageable); + Page allPost= postRepository.findByUserIdAndPostTypeAndState(userId, PostType.VOTE, PostState.POSTING, pageable); + List filterEndPost=allPost.getContent().stream() + .filter(post->{ + LocalDateTime deadline=null; + switch (post.getVoteType()){ + case GENERAL: + deadline=post.getGeneralPoll().getDeadline(); + break; + case GAUGE: + deadline=post.getGaugePoll().getDeadline(); + break; + case CARD: + deadline=post.getCardPoll().getDeadline(); + break; + } + return deadline !=null&&deadline.isBefore(LocalDateTime.now()); + }).collect(Collectors.toList()); + return new PageImpl<>(filterEndPost,pageable, filterEndPost.size()); + } } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 02d2c29..8a8d8b6 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -117,11 +117,11 @@ public ApiResponse getPostDetail(@PathVariab @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), - @Parameter(name = "category", description = "query string(RequestParam) - category(한글). 모두 보기는 '모두'라고 입력 하시면 됩니다.") + @Parameter(name = "category", description = "path variable - category(한글). 모두 보기는 '모두'라고 입력 하시면 됩니다.") }) - public ApiResponse getPostDetail(@RequestParam(name = "page", defaultValue = "0") Integer page, + public ApiResponse getPostAll(@RequestParam(name = "page", defaultValue = "0") Integer page, @RequestParam(name = "size",defaultValue = "15") Integer size, - @RequestParam(name = "category") String category, + @PathVariable(name = "category") String category, @RequestHeader("atk") String atk, HttpServletRequest request2){ Long userId=jwtTokenService.JwtToId(request2); @@ -138,7 +138,7 @@ public ApiResponse getPostDetail(@RequestPar @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정) 디폴트값 15"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) - public ApiResponse getReviewDetail(@RequestParam(name="arrange", defaultValue = "0") Integer arrange, + public ApiResponse getReviewAll(@RequestParam(name="arrange", defaultValue = "0") Integer arrange, @RequestParam(name = "page", defaultValue = "0") Integer page, @RequestParam(name = "size",defaultValue = "15") Integer size, @RequestHeader("atk") String atk, diff --git a/src/main/java/friend/spring/web/dto/ParentPostDTO.java b/src/main/java/friend/spring/web/dto/ParentPostDTO.java index 67f621b..f38f28f 100644 --- a/src/main/java/friend/spring/web/dto/ParentPostDTO.java +++ b/src/main/java/friend/spring/web/dto/ParentPostDTO.java @@ -12,6 +12,7 @@ @AllArgsConstructor public class ParentPostDTO { String nickname; + String userImg; String title; String content; List pollOption; diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 7952d6b..457c84b 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -26,6 +26,7 @@ public static class AddPostResultDTO { @AllArgsConstructor public static class PostDetailResponse { String nickname; + String userImg; LocalDateTime createdAt; String title; String content; @@ -63,7 +64,9 @@ public static class PollPostGetListDTO{ @NoArgsConstructor @AllArgsConstructor public static class PollPostGetResponse{ + Long postId; String nickname; + String userImg; String title; String content; LocalDateTime uploadDate; @@ -89,7 +92,9 @@ public static class ReviewPostGetListDTO{ @NoArgsConstructor @AllArgsConstructor public static class ReviewPostGetResponse{ + Long postId; String nickname; + String userImg; String title; String content; LocalDateTime uploadDate; From 051698f82c890f062679f0929254c4e1aef22e27 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sun, 11 Feb 2024 20:19:12 +0900 Subject: [PATCH 166/255] =?UTF-8?q?#104=20Feat=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/MyPageConverter.java | 13 ++++++++++++ .../friend/spring/service/MyPageService.java | 3 +++ .../spring/service/MyPageServiceImpl.java | 8 ++++++++ .../web/controller/MyPageRestController.java | 20 +++++++++++++++++++ .../spring/web/dto/MyPageResponseDTO.java | 11 ++++++++++ 5 files changed, 55 insertions(+) diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index c1a53d9..e32527c 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -50,4 +50,17 @@ public static MyPageResponseDTO.SavedAllPostResDTO toSavedAllPostResDTO(Page getAllPostList(Long userId, Integer page, Integer sort); void editUserImage(MultipartFile file, HttpServletRequest request); + + User getEditUserPage(Long userId); } diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index 31f02af..d2ab564 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -94,4 +94,12 @@ public void editUserImage(MultipartFile file, HttpServletRequest request) { File newFile = s3Service.uploadSingleImage(file, S3ImageType.USER, user, null); user.setFile(newFile); } + + @Override + public User getEditUserPage(Long userId) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + return user; + } + + } diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index 929b605..09ea0f8 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -5,6 +5,7 @@ import friend.spring.converter.MyPageConverter; import friend.spring.domain.Category; import friend.spring.domain.Post; +import friend.spring.domain.User; import friend.spring.domain.mapping.Comment_choice; import friend.spring.service.JwtTokenService; import friend.spring.service.MyPageService; @@ -99,4 +100,23 @@ public ApiResponse editUserImage( myPageService.editUserImage(file, request); return ApiResponse.onSuccess(null); } + + // 회원정보 수정 페이지 + @GetMapping(value = "/profile/modify") + @Operation(summary = "회원정보 수정 페이지 API", description = "회원정보 수정 페이지를 조회하는 API입니다. ex) /user/my-page/profile/modify") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) + public ApiResponse getEditUserPage( + @RequestHeader(name = "atk") String atk, + HttpServletRequest request + ) { + Long userId = jwtTokenService.JwtToId(request); + User editUserPage = myPageService.getEditUserPage(userId); + return ApiResponse.onSuccess(MyPageConverter.toMyProfileResDTO(editUserPage)); + } } diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index 7dbd491..77b8d66 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -46,4 +46,15 @@ public static class SavedPostResDTO{ public static class SavedAllPostResDTO{ List postList; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class MyProfileResDTO{ + String userImage; + String nickName; + String email; + String phone; + } } From 8b36731b304240f4615e9df10e1a1c7448198848 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Mon, 12 Feb 2024 00:14:32 +0900 Subject: [PATCH 167/255] =?UTF-8?q?#106=20Feat=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95(=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD,=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD)=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/MyPageConverter.java | 24 ++++++++++ src/main/java/friend/spring/domain/User.java | 4 ++ .../friend/spring/service/MyPageService.java | 5 ++ .../spring/service/MyPageServiceImpl.java | 15 ++++++ .../web/controller/MyPageRestController.java | 46 +++++++++++++++++-- .../spring/web/dto/MyPageRequestDTO.java | 38 +++++++++++++++ .../spring/web/dto/MyPageResponseDTO.java | 18 ++++++++ 7 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 src/main/java/friend/spring/web/dto/MyPageRequestDTO.java diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index e32527c..00d4474 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -4,6 +4,7 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.mapping.Post_scrap; +import friend.spring.web.dto.MyPageRequestDTO; import friend.spring.web.dto.MyPageResponseDTO; import org.springframework.data.domain.Page; @@ -63,4 +64,27 @@ public static MyPageResponseDTO.MyProfileResDTO toMyProfileResDTO(User user){ .phone(user.getPhone()) .build(); } + + public static User toUserName(MyPageRequestDTO.ProfileEditNameReq profileEditNameReq){ + return User.builder() + .nickname(profileEditNameReq.getNickName()) + .build(); + } + public static MyPageResponseDTO.ProfileEditNameRes toProfileEditNameResDTO(User user){ + return MyPageResponseDTO.ProfileEditNameRes.builder() + .nickName(user.getNickname()) + .build(); + } + + public static MyPageResponseDTO.ProfileEditEmailRes toProfileEditEmailResDTO(User user){ + return MyPageResponseDTO.ProfileEditEmailRes.builder() + .changeEmail(user.getEmail()) + .build(); + } + + public static User toUserEmail(MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq){ + return User.builder() + .email(profileEditEmailReq.getChangeEmail()) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index a1a8a35..bba43de 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -165,5 +165,9 @@ public void setPoint(Integer point) { public void setFile(File file) { this.file = file; } + + public void setNickname(String nickname){ this.nickname = nickname; } + + public void setEmail(String email){this.email = email;} } diff --git a/src/main/java/friend/spring/service/MyPageService.java b/src/main/java/friend/spring/service/MyPageService.java index 0fdb61d..cc33b46 100644 --- a/src/main/java/friend/spring/service/MyPageService.java +++ b/src/main/java/friend/spring/service/MyPageService.java @@ -4,6 +4,7 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.mapping.Post_scrap; +import friend.spring.web.dto.MyPageRequestDTO; import org.springframework.data.domain.Page; import org.springframework.web.multipart.MultipartFile; @@ -21,4 +22,8 @@ public interface MyPageService { void editUserImage(MultipartFile file, HttpServletRequest request); User getEditUserPage(Long userId); + + User editUserName(Long userId, MyPageRequestDTO.ProfileEditNameReq profileEditNameReq); + + User editUserEmail(Long userId, MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq); } diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index d2ab564..be7b5d5 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -15,6 +15,7 @@ import friend.spring.repository.PostScrapRepository; import friend.spring.repository.UserRepository; import friend.spring.security.JwtTokenProvider; +import friend.spring.web.dto.MyPageRequestDTO; import friend.spring.web.dto.MyPageResponseDTO; import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; @@ -101,5 +102,19 @@ public User getEditUserPage(Long userId) { return user; } + @Override + public User editUserName(Long userId, MyPageRequestDTO.ProfileEditNameReq profileEditNameReq) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + user.setNickname(profileEditNameReq.getNickName()); + return user; + } + + @Override + public User editUserEmail(Long userId, MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + user.setEmail(profileEditEmailReq.getChangeEmail()); + return user; + } + } diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index 09ea0f8..b2d0fac 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -7,11 +7,9 @@ import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.mapping.Comment_choice; -import friend.spring.service.JwtTokenService; -import friend.spring.service.MyPageService; -import friend.spring.service.PostService; -import friend.spring.service.UserService; +import friend.spring.service.*; import friend.spring.web.dto.CommentResponseDTO; +import friend.spring.web.dto.MyPageRequestDTO; import friend.spring.web.dto.MyPageResponseDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -24,6 +22,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; import java.util.List; @RestController @@ -35,6 +34,7 @@ public class MyPageRestController { private final MyPageService myPageService; private final JwtTokenService jwtTokenService; + private final EmailService emailService; //저장한 게시물(내 카테고리) 조회 @GetMapping("/post") @@ -119,4 +119,42 @@ public ApiResponse getEditUserPage( User editUserPage = myPageService.getEditUserPage(userId); return ApiResponse.onSuccess(MyPageConverter.toMyProfileResDTO(editUserPage)); } + + @PatchMapping(value = "/profile/modify/name") + @Operation(summary = "회원정보 이름 수정 API", description = "회원정보 이름을 수정하는 API입니다. ex) /user/my-page/profile/modify/name") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005",description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") + }) + public ApiResponse editUserName( + @RequestHeader(name = "atk") String atk, + HttpServletRequest request, + @RequestBody @Valid MyPageRequestDTO.ProfileEditNameReq profileEditNameReq){ + Long userId = jwtTokenService.JwtToId(request); + emailService.CheckAuthNum(profileEditNameReq.getEmail(), profileEditNameReq.getCertification()); + User editUserName = myPageService.editUserName(userId, profileEditNameReq); + return ApiResponse.onSuccess(MyPageConverter.toProfileEditNameResDTO(editUserName)); + } + + @PatchMapping(value = "/profile/modify/email") + @Operation(summary = "회원정보 이메일 수정 API", description = "회원정보 이메일을 수정하는 API입니다. ex) /user/my-page/profile/modify/email") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005",description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") + }) + public ApiResponse editUserEmail( + @RequestHeader(name = "atk") String atk, + HttpServletRequest request, + @RequestBody @Valid MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq){ + Long userId = jwtTokenService.JwtToId(request); + emailService.CheckAuthNum(profileEditEmailReq.getCurEmail(), profileEditEmailReq.getCertification()); + User editUserEmail = myPageService.editUserEmail(userId, profileEditEmailReq); + return ApiResponse.onSuccess(MyPageConverter.toProfileEditEmailResDTO(editUserEmail)); + } } diff --git a/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java b/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java new file mode 100644 index 0000000..d72805c --- /dev/null +++ b/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java @@ -0,0 +1,38 @@ +package friend.spring.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; + +public class MyPageRequestDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ProfileEditNameReq{ + @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 + //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 + @NotEmpty(message = "이메일을 입력해 주세요") + private String email; + private String certification; + String nickName; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ProfileEditEmailReq{ + @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 + //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 + @NotEmpty(message = "이메일을 입력해 주세요") + private String curEmail; + private String certification; + String changeEmail; + } +} diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index 77b8d66..7815fab 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -5,6 +5,8 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; import java.time.LocalDateTime; import java.util.List; import java.util.Set; @@ -57,4 +59,20 @@ public static class MyProfileResDTO{ String email; String phone; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ProfileEditNameRes{ + String nickName; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ProfileEditEmailRes{ + String changeEmail; + } } From 78966da7292028bae9cb2c6869886b9f7bb14a02 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 12 Feb 2024 11:07:05 +0900 Subject: [PATCH 168/255] =?UTF-8?q?#102=20Feat:=20=EA=B8=80=EC=93=B0?= =?UTF-8?q?=EA=B8=B0=EC=8B=9C=20=EB=94=94=ED=8F=B4=ED=8A=B8=EA=B0=92=20?= =?UTF-8?q?=ED=98=84=EC=9E=AC=EC=8B=9C=EA=B0=84+1=EC=8B=9C=EA=B0=84,=20?= =?UTF-8?q?=EC=8A=A4=EC=9B=A8=EA=B1=B0=20=EC=84=A4=EB=AA=85=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 35 ++----------------- .../spring/service/PostServiceImpl.java | 12 ++++--- .../web/controller/PostRestController.java | 2 +- 3 files changed, 10 insertions(+), 39 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 8d862a0..73bec37 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -115,18 +115,7 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ parentPollDTO.setCandidateImage(candidateImage); } -// // 1등 후보 이름, 사진 반환 -// Long id=parentPollDTO.getCandidateId(); -// Optional name = parentPost.getGeneralPoll().getCandidateList().stream() -// .filter(candidate -> candidate.getId().equals(id)) -// .map(Candidate::getName) -// .findFirst(); -// String candidateName=name.get(); -// String candidateImage = parentPollDTO.getCandidateImage(); -// -// -// parentPollDTO.setCandidateName(candidateName); -// parentPollDTO.setCandidateImage(candidateImage); + return ParentPostDTO.builder() .nickname(parentPost.getUser().getNickname()) @@ -177,31 +166,11 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ .map(Candidate::getName) .findFirst(); String candidateName=name.get(); -// Optional image = parentPost.getCardPoll().getCandidateList().stream() -// .filter(candidate -> candidate.getId().equals(id)) -// .map(Candidate::getFile) -// .findFirst(); + String candidateImage=parentPollDTO.getCandidateImage(); parentPollDTO.setCandidateName(candidateName); parentPollDTO.setCandidateImage(candidateImage); } -// // 1등 후보의 정보를 ParentPollDTO 객체로 반환 -// parentPollDTO = highestSelectionCandidate.get(); -// -// // 1등 후보 이름, 사진 반환 -// Long id=parentPollDTO.getCandidateId(); -// Optional name = parentPost.getGeneralPoll().getCandidateList().stream() -// .filter(candidate -> candidate.getId().equals(id)) -// .map(Candidate::getName) -// .findFirst(); -// String candidateName=name.get(); -// Optional image = parentPost.getGeneralPoll().getCandidateList().stream() -// .filter(candidate -> candidate.getId().equals(id)) -// .map(Candidate::getFile) -// .findFirst(); -// String candidateImage=image.get().getUrl(); -// parentPollDTO.setCandidateName(candidateName); -// parentPollDTO.setCandidateImage(candidateImage); return ParentPostDTO.builder() diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index e3da2fb..fdf5c65 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -113,8 +113,10 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque if (file != null) { s3Service.uploadPostImages(file, S3ImageType.POST, newPost); } - - + LocalDateTime deadline=request.getDeadline(); + if(request.getDeadline()==null){ + deadline=LocalDateTime.now().plusHours(1); + } //일반 투표 api if(newPost.getPostType()==VOTE){ @@ -139,7 +141,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque General_poll generalPoll = General_poll.builder() .pollTitle(request.getPollTitle()) - .deadline(request.getDeadline()) + .deadline(deadline) .build(); if(request.getMultipleChoice()!=null){ generalPoll.setMultipleChoice(request.getMultipleChoice()); @@ -170,7 +172,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque Card_poll cardPoll = Card_poll.builder() .pollTitle(request.getPollTitle()) - .deadline(request.getDeadline()) + .deadline(deadline) .build(); if(request.getMultipleChoice()!=null){ cardPoll.setMultipleChoice(request.getMultipleChoice()); @@ -201,7 +203,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque Gauge_poll gaugePoll = Gauge_poll.builder() .pollTitle(request.getPollTitle()) .gauge(0) - .deadline(request.getDeadline()) + .deadline(deadline) .build(); newPost.setGaugePoll(gaugePoll); diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 8a8d8b6..abfcc51 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -50,7 +50,7 @@ public class PostRestController { @Parameter(name="pollTitle", description=" 투표 제목"), @Parameter(name="multipleChoice", description=" 복수 선택 여부"), @Parameter(name="parent_id", description=" 원글(후기글 경우) id
해당 사항 없을시 null"), - @Parameter(name="deadline", description=" 투표 마감 시간
해당 사항 없을시 null"), + @Parameter(name="deadline", description=" 투표 마감 시간
해당 사항 없을시 null(기본값 1시간 이후)"), @Parameter(name="point", description=" 포인트
해당 사항 없을시 null") }) From fb7c6c19e56345ba8d8f7f110497ba6250a39ba1 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 12 Feb 2024 13:55:03 +0900 Subject: [PATCH 169/255] =?UTF-8?q?#108=20Refactor:=20=EB=8C=93=EA=B8=80?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20=EC=A2=8B=EC=95=84=EC=9A=94?= =?UTF-8?q?/=EA=B8=80=20=EC=A3=BC=EC=9D=B8/=EB=82=B4=EA=B0=80=20=EC=93=B4?= =?UTF-8?q?=20=EB=8C=93=EA=B8=80=20=EC=97=AC=EB=B6=80=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20&=20=EB=8C=93=EA=B8=80=20=EC=82=AD=EC=A0=9C=20api=20url?= =?UTF-8?q?=EC=97=90=EC=84=9C=20like=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/CommentConverter.java | 22 +++++---- .../friend/spring/service/CommentService.java | 2 +- .../spring/service/CommentServiceImpl.java | 48 ++++++++++++++++++- .../web/controller/CommentRestController.java | 8 ++-- .../spring/web/dto/CommentResponseDTO.java | 6 ++- 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index e4a7e23..3373d77 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class CommentConverter { public static Comment toComment(CommentRequestDTO.commentCreateReq request, Post post, User user, Comment parentComment) { @@ -42,25 +43,19 @@ public static CommentResponseDTO.commentLikeRes toCommentLikeRes(Comment_like co .build(); } - public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment) { + public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment, Long loginUserId, Boolean isPushedLike, Boolean isOwnerOfPost, List subComments) { Long parentCommentId = null; if (comment.getParentComment() != null) { parentCommentId = comment.getParentComment().getId(); } - List subComments = new ArrayList<>(); - if (comment.getSubCommentList() != null) { - for (Comment c : comment.getSubCommentList()) { - subComments.add(toCommentGetRes(c)); - } - } - // 유저 프로필 String userPhoto = null; if (comment.getUser().getFile() != null) { userPhoto = comment.getUser().getFile().getUrl(); } + // 댓글 삭제 여부 boolean isDeleted; if (comment.getState().equals(CommentState.DELETED)) { isDeleted = true; @@ -68,6 +63,14 @@ public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment) isDeleted = false; } + // 내가 쓴 댓글인지 여부 + boolean isMyComment; + if (Objects.equals(comment.getUser().getId(), loginUserId)) { + isMyComment = true; + } else { + isMyComment = false; + } + return CommentResponseDTO.commentGetRes.builder() .commentId(comment.getId()) .content(comment.getContent()) @@ -80,6 +83,9 @@ public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment) .commentLike(comment.getCommentLikeList().size()) .childrenComments(subComments) .isDeleted(isDeleted) + .isMyComment(isMyComment) + .isPushedLike(isPushedLike) + .isOwnerOfPost(isOwnerOfPost) .build(); } diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index 8aea81d..dac86fd 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -21,7 +21,7 @@ public interface CommentService { Comment_like likeComment(Long postId, Long commentId, HttpServletRequest request); - List getComments(Long postId); + List getComments(Long postId, HttpServletRequest request); void dislikeComment(Long postId, Long commentId, HttpServletRequest request); diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 5086516..95b0333 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -21,6 +21,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import software.amazon.awssdk.services.s3.endpoints.internal.Value; import javax.servlet.http.HttpServletRequest; import java.util.*; @@ -152,7 +153,13 @@ public Comment_like likeComment(Long postId, Long commentId, HttpServletRequest } @Override - public List getComments(Long postId) { + public List getComments(Long postId, HttpServletRequest request) { + Long loginUserId = jwtTokenProvider.getCurrentUser(request); + Optional optionalUser = userRepository.findById(loginUserId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { postService.checkPost(false); @@ -161,13 +168,50 @@ public List getComments(Long postId) { List commentList = commentRepository.findByPostIdAndParentCommentIsNull(postId); // 루트 댓글만 가져옴 List commentGetResList = new ArrayList<>(); for (Comment comment : commentList) { - CommentResponseDTO.commentGetRes commentGetRes = CommentConverter.toCommentGetRes(comment); + // 대댓글 처리 + List subComments = new ArrayList<>(); + if (comment.getSubCommentList() != null) { + for (Comment c : comment.getSubCommentList()) { + Boolean isPushedLike_sub = checkIsPushedLike(comment, loginUserId); + Boolean isOwnerOfPost_sub = checkIsOwnerOfPost(comment, loginUserId); + CommentResponseDTO.commentGetRes subCommentGetRes = CommentConverter.toCommentGetRes(comment, loginUserId, isPushedLike_sub, isOwnerOfPost_sub, null); + subComments.add(subCommentGetRes); + } + } + + Boolean isPushedLike = checkIsPushedLike(comment, loginUserId); + Boolean isOwnerOfPost = checkIsOwnerOfPost(comment, loginUserId); + + CommentResponseDTO.commentGetRes commentGetRes = CommentConverter.toCommentGetRes(comment, loginUserId, isPushedLike, isOwnerOfPost, subComments); commentGetResList.add(commentGetRes); } return commentGetResList; } + public Boolean checkIsPushedLike(Comment comment, Long loginUserId) { + // 좋아요 이미 눌렀는지 여부 + Optional optionalComment_like = commentLikeRepository.findByCommentIdAndUserId(comment.getId(), loginUserId); + Boolean isPushedLike; + if (optionalComment_like.isEmpty()) { + isPushedLike = false; + } else { + isPushedLike = true; + } + return isPushedLike; + } + + public Boolean checkIsOwnerOfPost(Comment comment, Long loginUserId) { + // 내가 쓴 글인지 여부 + Boolean isOwnerOfPost; + if (Objects.equals(comment.getPost().getUser().getId(), loginUserId)) { + isOwnerOfPost = true; + } else { + isOwnerOfPost = false; + } + return isOwnerOfPost; + } + @Override public void dislikeComment(Long postId, Long commentId, HttpServletRequest request) { Long userId = jwtTokenProvider.getCurrentUser(request); diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 38f8a16..8f23ed3 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -113,9 +113,11 @@ public ApiResponse dislikeComment( @Parameter(name = "post-id", description = "path variable - 글 아이디") }) public ApiResponse> getComments( - @PathVariable("post-id") Long postId + @PathVariable("post-id") Long postId, + @RequestHeader(name = "atk") String atk, + HttpServletRequest request ) { - return ApiResponse.onSuccess(commentService.getComments(postId)); + return ApiResponse.onSuccess(commentService.getComments(postId, request)); } // 댓글 채택 @@ -172,7 +174,7 @@ public ApiResponse editComment( } // 댓글 삭제 - @PatchMapping("/{post-id}/comment/{comment-id}/like/del") + @PatchMapping("/{post-id}/comment/{comment-id}/del") @Operation(summary = "댓글 삭제 API", description = "댓글 삭제하는 API입니다. ex) /posts/1/comment/1/del") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index 11634e5..f974a7a 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -4,6 +4,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import software.amazon.awssdk.services.s3.endpoints.internal.Value; import java.time.LocalDateTime; import java.util.List; @@ -40,8 +41,11 @@ public static class commentGetRes { LocalDateTime updatedAt; Long parentCommentId; Integer commentLike; - List childrenComments; Boolean isDeleted; // 댓글 삭제 여부 + Boolean isMyComment; // 내가 쓴 댓글인지 여부 + Boolean isPushedLike; // 좋아요 이미 눌렀는지 여부 + Boolean isOwnerOfPost; // 내가 쓴 글인지 여부 + List childrenComments; } @Builder From c5e41eb255b846e82a71b3334334322ee15542d7 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 12 Feb 2024 14:07:21 +0900 Subject: [PATCH 170/255] =?UTF-8?q?#108=20Refactor:=20=EB=8C=80=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EB=AA=A9=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/service/CommentServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 95b0333..701c28f 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -174,7 +174,7 @@ public List getComments(Long postId, HttpServl for (Comment c : comment.getSubCommentList()) { Boolean isPushedLike_sub = checkIsPushedLike(comment, loginUserId); Boolean isOwnerOfPost_sub = checkIsOwnerOfPost(comment, loginUserId); - CommentResponseDTO.commentGetRes subCommentGetRes = CommentConverter.toCommentGetRes(comment, loginUserId, isPushedLike_sub, isOwnerOfPost_sub, null); + CommentResponseDTO.commentGetRes subCommentGetRes = CommentConverter.toCommentGetRes(comment, loginUserId, isPushedLike_sub, isOwnerOfPost_sub, new ArrayList<>()); subComments.add(subCommentGetRes); } } From 331300c477a2b701466173d667595b860e0e4f56 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 12 Feb 2024 22:50:24 +0900 Subject: [PATCH 171/255] =?UTF-8?q?#113=20Refactor:=20=EC=9C=A0=EC=A0=80?= =?UTF-8?q?=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=82=AC=EC=A7=84=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=20=EC=9E=88=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/domain/File.java | 4 ++++ .../friend/spring/repository/FileRepository.java | 3 +++ .../friend/spring/service/MyPageServiceImpl.java | 15 ++++++++++----- .../java/friend/spring/service/S3Service.java | 11 ++++++++++- .../web/controller/MyPageRestController.java | 4 ++-- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/main/java/friend/spring/domain/File.java b/src/main/java/friend/spring/domain/File.java index 6e7cdc2..cf38e0d 100644 --- a/src/main/java/friend/spring/domain/File.java +++ b/src/main/java/friend/spring/domain/File.java @@ -29,4 +29,8 @@ public class File extends BaseEntity { // S3에 저장한 이미지 파일 링 @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; + + public void setUrl(String imageUrl){ + this.url = imageUrl; + } } diff --git a/src/main/java/friend/spring/repository/FileRepository.java b/src/main/java/friend/spring/repository/FileRepository.java index 9544859..33cc7f7 100644 --- a/src/main/java/friend/spring/repository/FileRepository.java +++ b/src/main/java/friend/spring/repository/FileRepository.java @@ -3,5 +3,8 @@ import friend.spring.domain.File; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface FileRepository extends JpaRepository { + Optional findByUserId(Long userId); } diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index be7b5d5..ac409f0 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -10,10 +10,7 @@ import friend.spring.domain.User; import friend.spring.domain.enums.S3ImageType; import friend.spring.domain.mapping.Post_scrap; -import friend.spring.repository.CategoryRepository; -import friend.spring.repository.PostRepository; -import friend.spring.repository.PostScrapRepository; -import friend.spring.repository.UserRepository; +import friend.spring.repository.*; import friend.spring.security.JwtTokenProvider; import friend.spring.web.dto.MyPageRequestDTO; import friend.spring.web.dto.MyPageResponseDTO; @@ -45,6 +42,7 @@ public class MyPageServiceImpl implements MyPageService{ private final PostRepository postRepository; private final CategoryRepository categoryRepository; private final PostScrapRepository postScrapRepository; + private final FileRepository fileRepository; private final JwtTokenProvider jwtTokenProvider; private final S3Service s3Service; @@ -92,7 +90,14 @@ public void editUserImage(MultipartFile file, HttpServletRequest request) { } User user = optionalUser.get(); - File newFile = s3Service.uploadSingleImage(file, S3ImageType.USER, user, null); + + Optional optionalFile = fileRepository.findByUserId(userId); + File newFile = null; + if (optionalFile.isPresent()) { // 이미 유저 프로필사진이 있는 경우 -> 기존 데이터 변경 + newFile = s3Service.editSingleImage(file, user); + } else { // 유저 프로필 사진이 없는 경우 -> 새로 데이터 추가 + newFile = s3Service.uploadSingleImage(file, S3ImageType.USER, user, null); + } user.setFile(newFile); } diff --git a/src/main/java/friend/spring/service/S3Service.java b/src/main/java/friend/spring/service/S3Service.java index d24c34b..5bdac03 100644 --- a/src/main/java/friend/spring/service/S3Service.java +++ b/src/main/java/friend/spring/service/S3Service.java @@ -40,7 +40,6 @@ public File uploadSingleImage(MultipartFile file, S3ImageType type, User user, C if (type == S3ImageType.USER && user != null) { // 사용자 프로필 이미지인 경우 String pictureUrl = s3Manager.uploadFile(s3Manager.generateUserKeyName(createFileName()), file); newFile = fileRepository.save(FileConverter.toFile(pictureUrl, user, null, null)); - } else { // 후보 이미지인 경우 String pictureUrl = s3Manager.uploadFile(s3Manager.generateCandidateKeyName(createFileName()), file); newFile = fileRepository.save(FileConverter.toFile(pictureUrl, null, null, candidate)); @@ -48,6 +47,16 @@ public File uploadSingleImage(MultipartFile file, S3ImageType type, User user, C return newFile; } + // 유저 프로필 사진 변경(이미 데이터가 있는 경우) + @Transactional + public File editSingleImage(MultipartFile file, User user) { + File newFile; + String pictureUrl = s3Manager.uploadFile(s3Manager.generateUserKeyName(createFileName()), file); + newFile = fileRepository.findByUserId(user.getId()).get(); + newFile.setUrl(pictureUrl); + return newFile; + } + // 먼저 파일 업로드시, 파일명을 난수화하기 위해 UUID 를 활용하여 난수를 돌린다. public Uuid createFileName() { diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index b2d0fac..8bd1c83 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -82,9 +82,9 @@ public ApiResponse getAllSavedPosts( return ApiResponse.onSuccess(MyPageConverter.toSavedAllPostResDTO(allPostList)); } - // 회원정보 수정(사용자 프로필 사진) + // 회원정보 사용자 프로필 사진 수정 @PatchMapping(value = "/profile/modify/image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @Operation(summary = "회원정보 수정(사용자 프로필 사진) API", description = "회원정보 수정(사용자 프로필 사진)하는 API입니다. ex) /user/my-page/profile/modify/image") + @Operation(summary = "회원정보 사용자 프로필 사진 수정 API", description = "사용자 프로필 사진을 수정하는 API입니다. ex) /user/my-page/profile/modify/image") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), From 6fb9cedf2070dba2093ebd3d99058301b52a2430 Mon Sep 17 00:00:00 2001 From: hjh Date: Mon, 12 Feb 2024 23:19:10 +0900 Subject: [PATCH 172/255] =?UTF-8?q?=EA=B8=80=20=EC=83=81=EC=84=B8=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0,=20=EA=B8=80=20=ED=88=AC=ED=91=9C=ED=95=98=EA=B8=B0?= =?UTF-8?q?=EC=8B=9C=20=EB=82=98=EB=85=B8=EC=B4=88=20=EB=8B=A8=EC=9C=84?= =?UTF-8?q?=EB=A1=9C=20=EB=A7=88=EA=B0=90=EC=8B=9C=EA=B0=84=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8,=20=EA=B8=80=20=EC=83=81=EC=84=B8=EB=B3=B4=EA=B8=B0?= =?UTF-8?q?=EC=8B=9C=20PostVoteType=20return=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 1 + .../spring/converter/PostConverter.java | 38 +++++++++++++++++-- .../spring/service/VoteServiceImpl.java | 26 +++++++++++++ .../spring/web/dto/PostResponseDTO.java | 5 +++ 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index be8b4f4..45bf23a 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -55,6 +55,7 @@ public enum ErrorStatus implements BaseErrorCode { NOT_ENOUGH_POINT(HttpStatus.BAD_REQUEST,"POST4013","해당 유저의 포인트가 부족 합니다"), POST_LIKE_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4014", "글에 대한 좋아요 데이터가 이미 존재합니다."), POST_SCRAP_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4015", "글에 대한 스크랩 데이터가 이미 존재합니다."), + DEADLINE_OVER(HttpStatus.BAD_REQUEST,"POST4016","투표 마감 시간이 지났습니다"), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 73bec37..d7db154 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -8,6 +8,7 @@ import org.springframework.data.domain.Page; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -258,6 +259,8 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B if(post.getPostType()==REVIEW){ return PostResponseDTO.PostDetailResponse.builder() + .postType(REVIEW) + .postVoteType(null) .nickname(post.getUser().getNickname()) .userImg(userImg) .createdAt(post.getCreatedAt()) @@ -274,17 +277,24 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .build(); } if(post.getVoteType()==PostVoteType.GAUGE){ + //나노초 단위로 마감 여부 확인 + LocalDateTime now = LocalDateTime.now(); + long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGaugePoll().getDeadline()); + Boolean voteOnGoing = nanosUntilDeadline > 0; + //투표에 참여 했을 경우 if(engage){ value=post.getGaugePoll().getGauge(); isVote=true; } return PostResponseDTO.PostDetailResponse.builder() + .postType(VOTE) + .postVoteType(PostVoteType.GAUGE) .nickname(post.getUser().getNickname()) .userImg(userImg) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .OnGoing(post.getGaugePoll().getVoteOnGoing()) + .OnGoing(voteOnGoing) .isVoted(isVote) .file(FileConverter.toFileDTO(post.getFileList())) .gauge(value) @@ -299,6 +309,12 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .build(); } if(post.getVoteType()==PostVoteType.GENERAL){ + //나노초 단위로 마감 여부 확인 + LocalDateTime now = LocalDateTime.now(); + long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGeneralPoll().getDeadline()); + Boolean voteOnGoing = nanosUntilDeadline > 0; + + //투표 후보 리스트 List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); if(engage) { @@ -380,12 +396,14 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B } } return PostResponseDTO.PostDetailResponse.builder() + .postType(VOTE) + .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) .userImg(userImg) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .OnGoing(post.getGeneralPoll().getVoteOnGoing()) + .OnGoing(voteOnGoing) .isVoted(isVote) .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getGeneralPoll().getPollTitle()) @@ -403,6 +421,11 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .myPost(myPost) .build(); } + //나노초 단위로 마감 여부 확인 + LocalDateTime now = LocalDateTime.now(); + long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getCardPoll().getDeadline()); + Boolean voteOnGoing = nanosUntilDeadline > 0; + List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); if(engage) { @@ -513,12 +536,14 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B } } return PostResponseDTO.PostDetailResponse.builder() + .postType(VOTE) + .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) .userImg(userImg) .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .OnGoing(post.getCardPoll().getVoteOnGoing()) + .OnGoing(voteOnGoing) .isVoted(isVote) .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getCardPoll().getPollTitle()) @@ -552,6 +577,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, if(post.getPostType()==VOTE&&post.getVoteType()==null){ return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) + .postVoteType(null) .nickname(post.getUser().getNickname()) .userImg(userImg) .content(Long.toString(post.getId())) @@ -584,6 +610,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) + .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) .userImg(userImg) .title(post.getTitle()) @@ -600,6 +627,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) + .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) .userImg(userImg) .title(post.getTitle()) @@ -619,6 +647,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, if(engage) { return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) + .postVoteType(PostVoteType.GAUGE) .nickname(post.getUser().getNickname()) .userImg(userImg) .title(post.getTitle()) @@ -633,6 +662,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) + .postVoteType(PostVoteType.GAUGE) .nickname(post.getUser().getNickname()) .userImg(userImg) .title(post.getTitle()) @@ -662,6 +692,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) + .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) .userImg(userImg) .title(post.getTitle()) @@ -678,6 +709,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) + .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) .userImg(userImg) .title(post.getTitle()) diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index e028685..595dcb9 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -10,6 +10,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -51,6 +53,13 @@ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request if (request.getSelectList() != null) { newGeneralVote.setSelect_list(request.getSelectList()); } + //나노초 단위로 마감 여부 확인 + LocalDateTime now = LocalDateTime.now(); + long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGeneralPoll().getDeadline()); + Boolean voteOnGoing = nanosUntilDeadline > 0; + if(!voteOnGoing){ + throw new GeneralException(ErrorStatus.DEADLINE_OVER); + } user.setPoint(user.getPoint() + 5); Point newPoint=Point.builder() @@ -77,6 +86,14 @@ public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long Gauge_poll gaugePoll=post.getGaugePoll(); newGaugeVote.setGaugePoll(gaugePoll); + //나노초 단위로 마감 여부 확인 + LocalDateTime now = LocalDateTime.now(); + long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGaugePoll().getDeadline()); + Boolean voteOnGoing = nanosUntilDeadline > 0; + if(!voteOnGoing){ + throw new GeneralException(ErrorStatus.DEADLINE_OVER); + } + user.setPoint(user.getPoint() + 5); Point newPoint=Point.builder() .amount(user.getPoint()) @@ -123,6 +140,15 @@ public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request,Long Pos if (request.getSelectList() != null) { newCardVote.setSelect_list(request.getSelectList()); } + + //나노초 단위로 마감 여부 확인 + LocalDateTime now = LocalDateTime.now(); + long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getCardPoll().getDeadline()); + Boolean voteOnGoing = nanosUntilDeadline > 0; + if(!voteOnGoing){ + throw new GeneralException(ErrorStatus.DEADLINE_OVER); + } + user.setPoint(user.getPoint() + 5); Point newPoint=Point.builder() .amount(user.getPoint()) diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 457c84b..cfcc552 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -1,4 +1,6 @@ package friend.spring.web.dto; +import friend.spring.domain.enums.PostType; +import friend.spring.domain.enums.PostVoteType; import friend.spring.validation.annotation.TitleTextLimit; import lombok.AllArgsConstructor; import lombok.Builder; @@ -25,6 +27,8 @@ public static class AddPostResultDTO { @NoArgsConstructor @AllArgsConstructor public static class PostDetailResponse { + PostType postType; + PostVoteType postVoteType; String nickname; String userImg; LocalDateTime createdAt; @@ -65,6 +69,7 @@ public static class PollPostGetListDTO{ @AllArgsConstructor public static class PollPostGetResponse{ Long postId; + PostVoteType postVoteType; String nickname; String userImg; String title; From 88e7232bf12ccc9f0b3b95823bd91d292e43326b Mon Sep 17 00:00:00 2001 From: park sang woo Date: Wed, 14 Feb 2024 01:46:59 +0900 Subject: [PATCH 173/255] =?UTF-8?q?=EC=B9=B4=EC=B9=B4=EC=98=A4=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../spring/converter/UserConverter.java | 50 ++++--- .../kakao/controller/AuthController.java | 40 ++++++ .../spring/kakao/converter/AuthConverter.java | 36 +++++ .../spring/kakao/domain/enums/SocialType.java | 5 + .../kakao/dto/response/AuthResponseDTO.java | 29 +++++ .../kakao/dto/response/KakaoProfile.java | 24 ++++ .../spring/kakao/dto/response/OAuthToken.java | 15 +++ .../kakao/provider/KakaoAuthProvider.java | 107 +++++++++++++++ .../spring/kakao/service/AuthService.java | 12 ++ .../spring/kakao/service/AuthServiceImpl.java | 123 ++++++++++++++++++ .../spring/repository/UserRepository.java | 2 + .../spring/security/JwtTokenProvider.java | 6 + .../spring/service/UserServiceImpl.java | 2 +- .../java/friend/spring/web/dto/TokenDTO.java | 4 +- .../spring/web/dto/UserResponseDTO.java | 25 ++-- src/main/resources/application.yml | 5 + 17 files changed, 455 insertions(+), 32 deletions(-) create mode 100644 src/main/java/friend/spring/kakao/controller/AuthController.java create mode 100644 src/main/java/friend/spring/kakao/converter/AuthConverter.java create mode 100644 src/main/java/friend/spring/kakao/domain/enums/SocialType.java create mode 100644 src/main/java/friend/spring/kakao/dto/response/AuthResponseDTO.java create mode 100644 src/main/java/friend/spring/kakao/dto/response/KakaoProfile.java create mode 100644 src/main/java/friend/spring/kakao/dto/response/OAuthToken.java create mode 100644 src/main/java/friend/spring/kakao/provider/KakaoAuthProvider.java create mode 100644 src/main/java/friend/spring/kakao/service/AuthService.java create mode 100644 src/main/java/friend/spring/kakao/service/AuthServiceImpl.java diff --git a/build.gradle b/build.gradle index 21d5080..1f95bca 100644 --- a/build.gradle +++ b/build.gradle @@ -43,6 +43,8 @@ dependencies { runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.4' // redis implementation 'org.springframework.boot:spring-boot-starter-data-redis' + //kakao +// implementation 'org.springframework.boot:spring-boot-starter-webflux' // S3 implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' implementation platform('software.amazon.awssdk:bom:2.20.56') diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index a36192b..d621c92 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -2,6 +2,7 @@ import friend.spring.domain.*; import friend.spring.domain.enums.Gender; +import friend.spring.kakao.dto.response.KakaoProfile; import friend.spring.web.dto.*; import friend.spring.domain.enums.RoleType; @@ -9,7 +10,6 @@ import java.time.LocalDateTime; import friend.spring.web.dto.UserResponseDTO; -import io.swagger.models.auth.In; import org.springframework.data.domain.Page; import java.util.List; @@ -19,8 +19,7 @@ public class UserConverter { - - public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ + public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user) { String userPhoto = null; if (user.getFile() != null) { userPhoto = user.getFile().getUrl(); @@ -30,28 +29,27 @@ public static UserResponseDTO.MyPageResDTO toMypageResDTO(User user){ .userPhoto(userPhoto) .userName(user.getNickname()) .userPoint(user.getPoint()) - .userLevelInt(user.getLevel().getLike()+1) + .userLevelInt(user.getLevel().getLike() + 1) .userLevelName(user.getLevel().getName()) .userRecommend(user.getLike()) .build(); } - public static UserResponseDTO.PointViewDTO toPointViewResDTO(Integer point){ + public static UserResponseDTO.PointViewDTO toPointViewResDTO(Integer point) { return UserResponseDTO.PointViewDTO.builder() .point(point) .build(); } - public static UserResponseDTO.EmailSendRes toEmailSendRes(String code) { return UserResponseDTO.EmailSendRes.builder() .code(code) .build(); } - public static UserResponseDTO.JoinResultDTO joinResultDTO(User user){ + public static UserResponseDTO.JoinResultDTO joinResultDTO(User user) { return UserResponseDTO.JoinResultDTO.builder() .email(user.getEmail()) .createAt(LocalDate.from(LocalDateTime.now())) @@ -60,11 +58,11 @@ public static UserResponseDTO.JoinResultDTO joinResultDTO(User user){ } - public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest, String pw, Level initLevel){ + public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest, String pw, Level initLevel) { Gender gender = null; - switch (userJoinRequest.getGender()){ + switch (userJoinRequest.getGender()) { case 1: gender = Gender.MALE; break; @@ -75,8 +73,6 @@ public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest, String gender = Gender.NONE; break; } - - return User.builder() .email(userJoinRequest.getEmail()) .password(pw) @@ -96,7 +92,7 @@ public static User toUser(UserRequestDTO.UserJoinRequest userJoinRequest, String } //나의 프로필(Q&A질문) - public static UserResponseDTO.QuestionResDTO toQuestionResDTO(User user, Level nxtLevel, Page postList, Page commentList){ + public static UserResponseDTO.QuestionResDTO toQuestionResDTO(User user, Level nxtLevel, Page postList, Page commentList) { //질문 목록 List myPostDTOList = postList.stream() .map(PostConverter::toMyPostResDTO).collect(Collectors.toList()); @@ -111,13 +107,13 @@ public static UserResponseDTO.QuestionResDTO toQuestionResDTO(User user, Level n .filter(comment -> comment.getCommentChoiceList().isEmpty()).collect(Collectors.toList()); //답변 채택률 int aChoice = all - myCommentList.size(); - double aChoicePercent = ((double)aChoice / (double)all) * 100; + double aChoicePercent = ((double) aChoice / (double) all) * 100; //질문 채택률 int Question = myPostDTOList.size(); List myPostList = postList.stream() .filter(post -> post.getCommentChoiceList().isEmpty()).collect(Collectors.toList()); - double pChoicePercent = ((double) (Question - myPostList.size()) / (double) Question)*100; + double pChoicePercent = ((double) (Question - myPostList.size()) / (double) Question) * 100; // 유저 프로필 String userPhoto = null; @@ -126,7 +122,7 @@ public static UserResponseDTO.QuestionResDTO toQuestionResDTO(User user, Level n } //남은 다음 등급 - double nxtGrade = ((double)user.getLike()/(double)(nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; + double nxtGrade = ((double) user.getLike() / (double) (nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; return UserResponseDTO.QuestionResDTO.builder() .userPhoto(userPhoto) .nickName(user.getNickname()) @@ -143,7 +139,7 @@ public static UserResponseDTO.QuestionResDTO toQuestionResDTO(User user, Level n } //나의 프로필(Q&A답변) - public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLevel, Page commentList){ + public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLevel, Page commentList) { //답변 목록 List myCommentDTOList = commentList.stream() .map(CommentConverter::toMyCommentResDTO).collect(Collectors.toList()); @@ -155,7 +151,7 @@ public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLe .filter(comment -> comment.getCommentChoiceList().isEmpty()).collect(Collectors.toList()); int choice = all - myCommentList.size(); //채택 답변률 - double percent = ((double)choice / (double)all) * 100.0; + double percent = ((double) choice / (double) all) * 100.0; // 유저 프로필 String userPhoto = null; @@ -164,7 +160,7 @@ public static UserResponseDTO.AnswerResDTO toAnswerResDTO(User user, Level nxtLe } //남은 다음 등급 - double nxtGrade = ((double)user.getLike()/(double)(nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; + double nxtGrade = ((double) user.getLike() / (double) (nxtLevel.getLike() - user.getLevel().getLike())) * 100.0; return UserResponseDTO.AnswerResDTO.builder() .userPhoto(userPhoto) .nickName(user.getNickname()) @@ -192,4 +188,20 @@ public static UserResponseDTO.UserSummaryInfo toUserSummaryInfo(User user) { .build(); } -} + public static UserResponseDTO.OAuthResponse toOAuthResponse( + TokenDTO accessToken, TokenDTO refreshToken, Boolean isLogin, User user) { + return UserResponseDTO.OAuthResponse.builder() + .refreshToken(refreshToken) + .accessToken(accessToken) + .isLogin(isLogin) + .email(user.getEmail()) + .build(); + } + + public static User KakaoUser( + KakaoProfile kakaoProfile){ + return User.builder() + .email(kakaoProfile.getKakao_account().getEmail()).build(); + + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/kakao/controller/AuthController.java b/src/main/java/friend/spring/kakao/controller/AuthController.java new file mode 100644 index 0000000..1c53e7b --- /dev/null +++ b/src/main/java/friend/spring/kakao/controller/AuthController.java @@ -0,0 +1,40 @@ +package friend.spring.kakao.controller; + +import friend.spring.apiPayload.ApiResponse; +import friend.spring.apiPayload.GeneralException; +import friend.spring.kakao.service.AuthService; +import friend.spring.service.JwtTokenService; +import friend.spring.service.UserService; +import friend.spring.web.dto.TokenDTO; +import friend.spring.web.dto.UserResponseDTO; +//import io.swagger.annotations.ApiResponse; +import org.springframework.web.bind.annotation.*; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/auth") +public class AuthController { + + private final AuthService authService; + private final JwtTokenService jwtTokenService; + private final UserService userService; + + @Operation(summary = "카카오 로그인 API", description = "카카오 로그인 및 회원 가입을 진행") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + }) + @GetMapping("/login/kakao") + public ApiResponse> kakaoLogin(@RequestParam("code") String code) throws GeneralException { + + return ApiResponse.onSuccess(authService.kakaoLogin(code)); + } +} +// @GetMapping("/login/kakao") +// public BaseResponse kakaoLogin(@RequestParam("code") String code) { +// return BaseResponse.onSuccess(authService.kakaoLogin(code)); +// } \ No newline at end of file diff --git a/src/main/java/friend/spring/kakao/converter/AuthConverter.java b/src/main/java/friend/spring/kakao/converter/AuthConverter.java new file mode 100644 index 0000000..5fc9278 --- /dev/null +++ b/src/main/java/friend/spring/kakao/converter/AuthConverter.java @@ -0,0 +1,36 @@ +package friend.spring.kakao.converter; + +import friend.spring.domain.User; +import friend.spring.domain.enums.RoleType; +import friend.spring.kakao.dto.response.KakaoProfile; +import friend.spring.web.dto.TokenDTO; +import friend.spring.web.dto.UserResponseDTO; + +public class AuthConverter { + + public static User kakaoUser(KakaoProfile kakaoProfile) { + return User.builder() + .nickname(kakaoProfile.getProperties().getNickname()) + .email(kakaoProfile.getKakao_account().getEmail()) + .role(RoleType.USER) + .build(); + } + + public static UserResponseDTO.OAuthResponse toOAuthResponse( + TokenDTO accessToken, TokenDTO refreshToken,Boolean isLogin, User user) { + return UserResponseDTO.OAuthResponse.builder() + .refreshToken(refreshToken) + .accessToken(accessToken) + .isLogin(isLogin) + .email(user.getEmail()) + .build(); + } + +// public static AuthResponseDTO.TokenRefreshResponse toTokenRefreshResponse( +// TokenDTO accessToken, TokenDTO refreshToken) { +// return AuthResponseDTO.TokenRefreshResponse.builder() +// .accessToken(accessToken) +// .refreshToken(refreshToken) +// .build(); +// } +} diff --git a/src/main/java/friend/spring/kakao/domain/enums/SocialType.java b/src/main/java/friend/spring/kakao/domain/enums/SocialType.java new file mode 100644 index 0000000..9371e30 --- /dev/null +++ b/src/main/java/friend/spring/kakao/domain/enums/SocialType.java @@ -0,0 +1,5 @@ +package friend.spring.kakao.domain.enums; + +public enum SocialType { + KAKAO +} diff --git a/src/main/java/friend/spring/kakao/dto/response/AuthResponseDTO.java b/src/main/java/friend/spring/kakao/dto/response/AuthResponseDTO.java new file mode 100644 index 0000000..ec60c90 --- /dev/null +++ b/src/main/java/friend/spring/kakao/dto/response/AuthResponseDTO.java @@ -0,0 +1,29 @@ +//package friend.spring.kakao.dto.response; +// +//import friend.spring.web.dto.TokenDTO; +//import lombok.*; +// +//public class AuthResponseDTO { +// +// @Getter +// @Builder +// @AllArgsConstructor(access = AccessLevel.PROTECTED) +// @NoArgsConstructor(access = AccessLevel.PROTECTED) +// public static class OAuthResponse { +// +// Long userId; +// TokenDTO accessToken; +// TokenDTO refreshToken; +// Boolean isLogin; +// } +// +// @Getter +// @Builder +// @AllArgsConstructor(access = AccessLevel.PROTECTED) +// @NoArgsConstructor(access = AccessLevel.PROTECTED) +// public static class TokenRefreshResponse { +// +// TokenDTO accessToken; +// TokenDTO refreshToken; +// } +//} \ No newline at end of file diff --git a/src/main/java/friend/spring/kakao/dto/response/KakaoProfile.java b/src/main/java/friend/spring/kakao/dto/response/KakaoProfile.java new file mode 100644 index 0000000..065d6bc --- /dev/null +++ b/src/main/java/friend/spring/kakao/dto/response/KakaoProfile.java @@ -0,0 +1,24 @@ +package friend.spring.kakao.dto.response; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Getter; + +@Getter +@JsonIgnoreProperties(ignoreUnknown = true) +public class KakaoProfile { + + private Properties properties; + private KakaoAccount kakao_account; + + @Getter + @JsonIgnoreProperties(ignoreUnknown = true) + public class Properties { + private String nickname; + } + + @Getter + @JsonIgnoreProperties(ignoreUnknown = true) + public class KakaoAccount { + private String email; + } +} diff --git a/src/main/java/friend/spring/kakao/dto/response/OAuthToken.java b/src/main/java/friend/spring/kakao/dto/response/OAuthToken.java new file mode 100644 index 0000000..36143da --- /dev/null +++ b/src/main/java/friend/spring/kakao/dto/response/OAuthToken.java @@ -0,0 +1,15 @@ +package friend.spring.kakao.dto.response; + +import lombok.Data; + +@Data +public class OAuthToken { + + private String access_token; + private String token_type; + private String refresh_token; + private String id_token; + private int expires_in; + private String scope; + private int refresh_token_expires_in; +} diff --git a/src/main/java/friend/spring/kakao/provider/KakaoAuthProvider.java b/src/main/java/friend/spring/kakao/provider/KakaoAuthProvider.java new file mode 100644 index 0000000..a38a669 --- /dev/null +++ b/src/main/java/friend/spring/kakao/provider/KakaoAuthProvider.java @@ -0,0 +1,107 @@ +package friend.spring.kakao.provider; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.kakao.dto.response.KakaoProfile; +import friend.spring.kakao.dto.response.OAuthToken; +import friend.spring.security.PrincipalDetailService; +import org.springframework.beans.factory.annotation.Value; +import friend.spring.repository.UserRepository; +import friend.spring.security.JwtTokenProvider; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.cache.CacheProperties; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +@Component +@RequiredArgsConstructor +public class KakaoAuthProvider { + + private final PrincipalDetailService principalDetailService; + private final UserRepository userRepository; + private final JwtTokenProvider jwtTokenProvider; +// private final RefreshTokenService refreshTokenService; + + @Value("${kakao.auth.client}") + private String client; + + @Value("${kakao.auth.redirect-uri}") + private String redirect; + + @Value("${kakao.auth.secret_key}") + private String secretKey; + + // code로 access 토큰 요청하기 + public OAuthToken requestToken(String code) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + + headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("grant_type", "authorization_code"); + params.add("client_id", client); + params.add("redirect_uri", redirect); + params.add("secret_key", secretKey); + params.add("code", code); + + HttpEntity> kakaoTokenRequest = + new HttpEntity<>(params, headers); + + ResponseEntity response = + restTemplate.exchange( + "https://kauth.kakao.com/oauth/token", + HttpMethod.POST, + kakaoTokenRequest, + String.class); + + ObjectMapper objectMapper = new ObjectMapper(); + + OAuthToken oAuthToken = null; + + try { + oAuthToken = objectMapper.readValue(response.getBody(), OAuthToken.class); + } catch (JsonProcessingException e) { + throw new GeneralException(ErrorStatus.INVALID_REQUEST_INFO); + } + + return oAuthToken; + } + + // Token으로 정보 요청하기 + public KakaoProfile requestKakaoProfile(String token) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); + headers.add("Authorization", "Bearer " + token); + + HttpEntity> kakaoProfileRequest = new HttpEntity<>(headers); + + ResponseEntity response = + restTemplate.exchange( + "https://kapi.kakao.com/v2/user/me", + HttpMethod.POST, + kakaoProfileRequest, + String.class); + + ObjectMapper objectMapper = new ObjectMapper(); + KakaoProfile kakaoProfile = null; + + try { + kakaoProfile = objectMapper.readValue(response.getBody(), KakaoProfile.class); + } catch (JsonProcessingException e) { + throw new GeneralException(ErrorStatus.INVALID_REQUEST_INFO); + } + + return kakaoProfile; + } +} diff --git a/src/main/java/friend/spring/kakao/service/AuthService.java b/src/main/java/friend/spring/kakao/service/AuthService.java new file mode 100644 index 0000000..f1e2682 --- /dev/null +++ b/src/main/java/friend/spring/kakao/service/AuthService.java @@ -0,0 +1,12 @@ +package friend.spring.kakao.service; + +import friend.spring.web.dto.TokenDTO; + +import java.util.List; + +public interface AuthService { + + List kakaoLogin(String code); + +// void logout(Long userId); +} diff --git a/src/main/java/friend/spring/kakao/service/AuthServiceImpl.java b/src/main/java/friend/spring/kakao/service/AuthServiceImpl.java new file mode 100644 index 0000000..86e6119 --- /dev/null +++ b/src/main/java/friend/spring/kakao/service/AuthServiceImpl.java @@ -0,0 +1,123 @@ +package friend.spring.kakao.service; + +import friend.spring.apiPayload.ApiResponse; +import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.handler.UserHandler; +import friend.spring.converter.UserConverter; +import friend.spring.domain.User; +import friend.spring.kakao.dto.response.KakaoProfile; +import friend.spring.kakao.dto.response.OAuthToken; +import friend.spring.kakao.provider.KakaoAuthProvider; +import friend.spring.repository.UserRepository; +import friend.spring.security.JwtTokenProvider; +import friend.spring.service.UserService; +import friend.spring.web.dto.TokenDTO; +import friend.spring.web.dto.UserRequestDTO; +import friend.spring.web.dto.UserResponseDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import static friend.spring.apiPayload.code.status.ErrorStatus.*; + +@Service +@RequiredArgsConstructor +public class AuthServiceImpl implements AuthService { + + private final KakaoAuthProvider kakaoAuthProvider; + private final UserRepository userRepository; + private final JwtTokenProvider jwtTokenProvider; + private final RedisTemplate redisTemplate; +// private final RefreshTokenService refreshTokenService; + + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + + @Override + @Transactional + public List kakaoLogin(String code) { + OAuthToken oAuthToken = kakaoAuthProvider.requestToken(code); + KakaoProfile kakaoProfile = + kakaoAuthProvider.requestKakaoProfile(oAuthToken.getAccess_token()); + + System.out.println(kakaoProfile.getKakao_account().getEmail()); + // 유저 정보 받기 + Optional queryUser = + userRepository.findByEmail( + kakaoProfile.getKakao_account().getEmail()); + System.out.println(queryUser.get().getEmail()); + System.out.println(queryUser.get().getBirth()); +// 가입자 혹은 비가입자 체크해서 로그인 처리 + if (queryUser.isPresent()) { + User user = queryUser.get(); + TokenDTO accessToken = jwtTokenProvider.createAccessToken(user.getEmail()); + TokenDTO refreshToken = jwtTokenProvider.createRefreshToken(user.getEmail()); + redisTemplate.opsForValue().set("RT:"+user.getEmail(),refreshToken.getToken(),refreshToken.getTokenExpriresTime().getTime(),TimeUnit.MILLISECONDS); + + List tokenDTOList = new ArrayList<>(); + tokenDTOList.add(refreshToken); + tokenDTOList.add(accessToken); + + return tokenDTOList; + } else { + User user = userRepository.save(UserConverter.KakaoUser(kakaoProfile)); + TokenDTO accessToken = jwtTokenProvider.createAccessToken(user.getEmail()); + TokenDTO refreshToken = jwtTokenProvider.createRefreshToken(user.getEmail()); + redisTemplate.opsForValue().set("RT:" + refreshToken, TimeUnit.MILLISECONDS); + + return (List) UserConverter.toOAuthResponse(accessToken, refreshToken, false, user); +//ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ +// if (queryUser.isPresent()) { +// User user = userRepository.findByEmail(kakaoProfile.getKakao_account().getEmail()) +// .orElseThrow(() -> new GeneralException(USERS_NOT_FOUND_EMAIL));//가입 안된 이메일 +// if (!encoder.matches(kakaoProfile.getKakao_account().getEmail(), user.getPassword())) { +// throw new GeneralException(PASSWORD_INCORRECT); //비밀번호 불일치, 계정없음 +// } +// //토큰발급 +// TokenDTO accessToken = jwtTokenProvider.createAccessToken(user.getEmail()); +// TokenDTO refreshToken = jwtTokenProvider.createRefreshToken(user.getEmail()); +// +// // login 시 Redis에 RT:gominchingy@gmail.com(key): --refresh token실제값--(value) 형태로 refresh 토큰 저장하기 +// // opsForValue() : set을 통해 key,value값 저장하고 get(key)통해 value가져올 수 있음. +// // refreshToken.getTokenExpriresTime().getTime() : 리프레시 토큰의 만료시간이 지나면 해당 값 자동 삭제 +// redisTemplate.opsForValue().set("RT:" + user.getEmail(), refreshToken.getToken(), refreshToken.getTokenExpriresTime().getTime(), TimeUnit.MILLISECONDS); +// +// List tokenDTOList = new ArrayList<>(); +// tokenDTOList.add(accessToken); +// tokenDTOList.add(refreshToken); +// System.out.println(tokenDTOList); +// +// return tokenDTOList; +// } +// return UserResponseDTO.OAuthResponse(); + } + } +} +// @Override +// @Transactional +// public JwtTokenProvider refresh(String refreshToken) { +// jwtTokenProvider.validateToken(refreshToken); +// +// if (!jwtTokenProvider.validateToken(refreshToken)) { +// throw new GeneralException(ErrorStatus.NOT_EQUAL_TOKEN); +// } +// +// TokenDTO accessToken = +// jwtTokenProvider.createAccessToken(jwtTokenProvider.getemail(refreshToken)); +// TokenDTO newRefreshToken = +// jwtTokenProvider.createAccessToken(jwtTokenProvider.getemail(refreshToken)); +//// refreshTokenService.saveToken(newRefreshToken); +// return AuthConverter.toTokenRefreshResponse(accessToken, refreshToken); +// } + +// public void logout(Long userId) { +//// refreshTokenService.deleteToken(userId); +//// } +//} \ No newline at end of file diff --git a/src/main/java/friend/spring/repository/UserRepository.java b/src/main/java/friend/spring/repository/UserRepository.java index ac0ca2d..f9ecd6b 100644 --- a/src/main/java/friend/spring/repository/UserRepository.java +++ b/src/main/java/friend/spring/repository/UserRepository.java @@ -1,6 +1,7 @@ package friend.spring.repository; import friend.spring.domain.User; +import friend.spring.domain.enums.RoleType; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -11,6 +12,7 @@ public interface UserRepository extends JpaRepository { Optional findByEmail(String email); Optional findByNickname(String nickname); +// Optional findByEmailAndRole(String email, RoleType roleType); Boolean existsByEmail(String email); Boolean existsByNickname(String nickname); diff --git a/src/main/java/friend/spring/security/JwtTokenProvider.java b/src/main/java/friend/spring/security/JwtTokenProvider.java index 12880b2..ca7b91a 100644 --- a/src/main/java/friend/spring/security/JwtTokenProvider.java +++ b/src/main/java/friend/spring/security/JwtTokenProvider.java @@ -166,4 +166,10 @@ public Long getCurrentUser(HttpServletRequest request) throws GeneralException { return userIdx; } +// public String getemail(String token) { +// return getClaims(token).getBody().get("id", String.class); +// } +// private Jws getClaims(String token) { +// return Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token); +// } } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 88e5218..7ac5b29 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -161,7 +161,7 @@ public String logout(HttpServletRequest request) { // Refresh Token 삭제 redisTemplate.delete("RT:" + user.getEmail()); } - // 해당 AccessToken 유효시간 가지고 와서 BlackList 로 저장하기 + // 해당 AccessToken 유효시간 가지고 와서 저장하기 String accessToken = jwtTokenProvider.resolveAccessToken(request); Long expiration = jwtTokenProvider.getExpireTime(accessToken).getTime(); // Redis 에 --accesstoken--(key) : logout(value) 로 저장, token 만료시간 지나면 자동 삭제 diff --git a/src/main/java/friend/spring/web/dto/TokenDTO.java b/src/main/java/friend/spring/web/dto/TokenDTO.java index 5d51035..9c67a31 100644 --- a/src/main/java/friend/spring/web/dto/TokenDTO.java +++ b/src/main/java/friend/spring/web/dto/TokenDTO.java @@ -11,9 +11,9 @@ @AllArgsConstructor public class TokenDTO { -// //1. 로그인 시 토큰을 응답 + //1. 로그인 시 토큰을 응답 + // private String token; // jwt 토큰 private String types; // atk, rtk -// private String token; // jwt 토큰 private String token; private Date tokenExpriresTime; // 토큰 만료시간 diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index fb3a48c..41e0774 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -8,6 +8,8 @@ public class UserResponseDTO { +// public static List LoginResDTO; + @Builder @Getter @NoArgsConstructor @@ -107,24 +109,27 @@ public static class LoginResDTO { String refreshToken; String tokenExpiresTime; - } -// @Getter -// @Builder -// @AllArgsConstructor(access = AccessLevel.PROTECTED) -// @NoArgsConstructor(access = AccessLevel.PROTECTED) -// public static class TokenRefreshResponse { -// -// String accessToken; -// String refreshToken; -// } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class OAuthResponse { + + Boolean isLogin; + TokenDTO accessToken; + TokenDTO refreshToken; + String email; + + } @NoArgsConstructor @AllArgsConstructor @Getter @Builder public static class UserSummaryInfo { + Long user_id; String nickname; String image; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9137343..f5af034 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -62,4 +62,9 @@ mail: AdminMail: id: ${gmail.username} password: ${gmail.password} +kakao: + auth: + client: 58d29ff7378109a321d4edc551a773c2 + redirect-uri: http://localhost:3000/api/auth/callback/kakao + secret_key: OSzm4b9sGFMZ982joQAkhZ7Fpiph4eOY From 1dc60cb9c0ace2ba32ea46710df96fa849625443 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Wed, 14 Feb 2024 01:56:05 +0900 Subject: [PATCH 174/255] =?UTF-8?q?=EC=B9=B4=EC=B9=B4=EC=98=A4=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kakao/controller/AuthController.java | 4 -- .../kakao/dto/response/AuthResponseDTO.java | 29 ----------- .../spring/kakao/service/AuthServiceImpl.java | 49 +------------------ 3 files changed, 2 insertions(+), 80 deletions(-) delete mode 100644 src/main/java/friend/spring/kakao/dto/response/AuthResponseDTO.java diff --git a/src/main/java/friend/spring/kakao/controller/AuthController.java b/src/main/java/friend/spring/kakao/controller/AuthController.java index 1c53e7b..222b0d7 100644 --- a/src/main/java/friend/spring/kakao/controller/AuthController.java +++ b/src/main/java/friend/spring/kakao/controller/AuthController.java @@ -34,7 +34,3 @@ public ApiResponse> kakaoLogin(@RequestParam("code") String code) return ApiResponse.onSuccess(authService.kakaoLogin(code)); } } -// @GetMapping("/login/kakao") -// public BaseResponse kakaoLogin(@RequestParam("code") String code) { -// return BaseResponse.onSuccess(authService.kakaoLogin(code)); -// } \ No newline at end of file diff --git a/src/main/java/friend/spring/kakao/dto/response/AuthResponseDTO.java b/src/main/java/friend/spring/kakao/dto/response/AuthResponseDTO.java deleted file mode 100644 index ec60c90..0000000 --- a/src/main/java/friend/spring/kakao/dto/response/AuthResponseDTO.java +++ /dev/null @@ -1,29 +0,0 @@ -//package friend.spring.kakao.dto.response; -// -//import friend.spring.web.dto.TokenDTO; -//import lombok.*; -// -//public class AuthResponseDTO { -// -// @Getter -// @Builder -// @AllArgsConstructor(access = AccessLevel.PROTECTED) -// @NoArgsConstructor(access = AccessLevel.PROTECTED) -// public static class OAuthResponse { -// -// Long userId; -// TokenDTO accessToken; -// TokenDTO refreshToken; -// Boolean isLogin; -// } -// -// @Getter -// @Builder -// @AllArgsConstructor(access = AccessLevel.PROTECTED) -// @NoArgsConstructor(access = AccessLevel.PROTECTED) -// public static class TokenRefreshResponse { -// -// TokenDTO accessToken; -// TokenDTO refreshToken; -// } -//} \ No newline at end of file diff --git a/src/main/java/friend/spring/kakao/service/AuthServiceImpl.java b/src/main/java/friend/spring/kakao/service/AuthServiceImpl.java index 86e6119..921c97e 100644 --- a/src/main/java/friend/spring/kakao/service/AuthServiceImpl.java +++ b/src/main/java/friend/spring/kakao/service/AuthServiceImpl.java @@ -59,7 +59,7 @@ public List kakaoLogin(String code) { User user = queryUser.get(); TokenDTO accessToken = jwtTokenProvider.createAccessToken(user.getEmail()); TokenDTO refreshToken = jwtTokenProvider.createRefreshToken(user.getEmail()); - redisTemplate.opsForValue().set("RT:"+user.getEmail(),refreshToken.getToken(),refreshToken.getTokenExpriresTime().getTime(),TimeUnit.MILLISECONDS); + redisTemplate.opsForValue().set("RT:" + user.getEmail(), refreshToken.getToken(), refreshToken.getTokenExpriresTime().getTime(), TimeUnit.MILLISECONDS); List tokenDTOList = new ArrayList<>(); tokenDTOList.add(refreshToken); @@ -73,51 +73,6 @@ public List kakaoLogin(String code) { redisTemplate.opsForValue().set("RT:" + refreshToken, TimeUnit.MILLISECONDS); return (List) UserConverter.toOAuthResponse(accessToken, refreshToken, false, user); -//ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ -// if (queryUser.isPresent()) { -// User user = userRepository.findByEmail(kakaoProfile.getKakao_account().getEmail()) -// .orElseThrow(() -> new GeneralException(USERS_NOT_FOUND_EMAIL));//가입 안된 이메일 -// if (!encoder.matches(kakaoProfile.getKakao_account().getEmail(), user.getPassword())) { -// throw new GeneralException(PASSWORD_INCORRECT); //비밀번호 불일치, 계정없음 -// } -// //토큰발급 -// TokenDTO accessToken = jwtTokenProvider.createAccessToken(user.getEmail()); -// TokenDTO refreshToken = jwtTokenProvider.createRefreshToken(user.getEmail()); -// -// // login 시 Redis에 RT:gominchingy@gmail.com(key): --refresh token실제값--(value) 형태로 refresh 토큰 저장하기 -// // opsForValue() : set을 통해 key,value값 저장하고 get(key)통해 value가져올 수 있음. -// // refreshToken.getTokenExpriresTime().getTime() : 리프레시 토큰의 만료시간이 지나면 해당 값 자동 삭제 -// redisTemplate.opsForValue().set("RT:" + user.getEmail(), refreshToken.getToken(), refreshToken.getTokenExpriresTime().getTime(), TimeUnit.MILLISECONDS); -// -// List tokenDTOList = new ArrayList<>(); -// tokenDTOList.add(accessToken); -// tokenDTOList.add(refreshToken); -// System.out.println(tokenDTOList); -// -// return tokenDTOList; -// } -// return UserResponseDTO.OAuthResponse(); } } -} -// @Override -// @Transactional -// public JwtTokenProvider refresh(String refreshToken) { -// jwtTokenProvider.validateToken(refreshToken); -// -// if (!jwtTokenProvider.validateToken(refreshToken)) { -// throw new GeneralException(ErrorStatus.NOT_EQUAL_TOKEN); -// } -// -// TokenDTO accessToken = -// jwtTokenProvider.createAccessToken(jwtTokenProvider.getemail(refreshToken)); -// TokenDTO newRefreshToken = -// jwtTokenProvider.createAccessToken(jwtTokenProvider.getemail(refreshToken)); -//// refreshTokenService.saveToken(newRefreshToken); -// return AuthConverter.toTokenRefreshResponse(accessToken, refreshToken); -// } - -// public void logout(Long userId) { -//// refreshTokenService.deleteToken(userId); -//// } -//} \ No newline at end of file +} \ No newline at end of file From 989d7ed92e55e92860013d307eb00265b8431004 Mon Sep 17 00:00:00 2001 From: hjh Date: Wed, 14 Feb 2024 02:06:03 +0900 Subject: [PATCH 175/255] =?UTF-8?q?#118=20=EA=B8=80=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0,=20=EA=B3=A0=EB=AF=BC=EA=B8=80=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=EB=B3=B4=EA=B8=B0=EC=8B=9C=20=EA=B2=8C=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=ED=88=AC=ED=91=9C=20=ED=95=9C=EC=A0=95=20PollTitle=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/PostConverter.java | 3 +++ src/main/java/friend/spring/web/dto/PostResponseDTO.java | 1 + 2 files changed, 4 insertions(+) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index d7db154..22927ed 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -297,6 +297,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .OnGoing(voteOnGoing) .isVoted(isVote) .file(FileConverter.toFileDTO(post.getFileList())) + .pollTitle(post.getGaugePoll().getPollTitle()) .gauge(value) .point(post.getPoint()) .deadline(post.getGaugePoll().getDeadline()) @@ -653,6 +654,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .title(post.getTitle()) .content(post.getContent()) .uploadDate(post.getCreatedAt()) + .pollTitle(post.getGaugePoll().getPollTitle()) .gauge(post.getGaugePoll().getGauge()) .like(likeCount) .comment(commentCount) @@ -668,6 +670,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .title(post.getTitle()) .content(post.getContent()) .uploadDate(post.getCreatedAt()) + .pollTitle(post.getGaugePoll().getPollTitle()) .like(likeCount) .comment(commentCount) .isLike(isLike) diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index cfcc552..986af31 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -77,6 +77,7 @@ public static class PollPostGetResponse{ LocalDateTime uploadDate; List pollOption; List userVote; + String pollTitle; //게이지투표만 해당(게이지 투표 이름) Integer gauge; Integer like; Integer comment; From fd2273f56eafbbe519bd02a9f16d308e80eca6d3 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Wed, 14 Feb 2024 07:20:26 +0900 Subject: [PATCH 176/255] =?UTF-8?q?#110=20Feat=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95(=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD,=20=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD)=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 1 + .../spring/converter/MyPageConverter.java | 12 ++++++ src/main/java/friend/spring/domain/User.java | 4 ++ .../friend/spring/service/MyPageService.java | 3 ++ .../spring/service/MyPageServiceImpl.java | 24 ++++++++++++ .../web/controller/MyPageRestController.java | 38 +++++++++++++++++++ .../spring/web/dto/MyPageRequestDTO.java | 25 +++++++++++- .../spring/web/dto/MyPageResponseDTO.java | 16 ++++++++ 8 files changed, 122 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index be8b4f4..d479e23 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -27,6 +27,7 @@ public enum ErrorStatus implements BaseErrorCode { EMPTY_JWT(HttpStatus.BAD_REQUEST, "USER4006", "JWT를 입력해주세요."), INVALID_JWT(HttpStatus.UNAUTHORIZED, "USER4007", "유효하지 않은 JWT입니다."), PASSWORD_INCORRECT(HttpStatus.NOT_FOUND, "USER4008", "비밀번호가 틀렸습니다."), + PASSWORD_CHECK_INCORRECT(HttpStatus.NOT_FOUND, "USER4009", "확인 비밀번호가 일치하지 않습니다."), RTK_INCORREXT(HttpStatus.UNAUTHORIZED,"USER4100","RefreshToken값을 확인해주세요."), // Auth 관련 diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index 00d4474..eafb923 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -87,4 +87,16 @@ public static User toUserEmail(MyPageRequestDTO.ProfileEditEmailReq profileEditE .email(profileEditEmailReq.getChangeEmail()) .build(); } + + public static MyPageResponseDTO.ProfileEditPhoneRes toProfileEditPhoneResDTO(User user){ + return MyPageResponseDTO.ProfileEditPhoneRes.builder() + .phone(user.getPhone()) + .build(); + } + + public static MyPageResponseDTO.ProfileEditPasswordRes toProfileEditPasswordResDTO(User user){ + return MyPageResponseDTO.ProfileEditPasswordRes.builder() + .changePassword(user.getPassword()) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index bba43de..b2d243d 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -169,5 +169,9 @@ public void setFile(File file) { public void setNickname(String nickname){ this.nickname = nickname; } public void setEmail(String email){this.email = email;} + + public void setPhone(String phone){this.phone = phone;} + + public void setPassword(String password){this.password = password;} } diff --git a/src/main/java/friend/spring/service/MyPageService.java b/src/main/java/friend/spring/service/MyPageService.java index cc33b46..3235fdc 100644 --- a/src/main/java/friend/spring/service/MyPageService.java +++ b/src/main/java/friend/spring/service/MyPageService.java @@ -26,4 +26,7 @@ public interface MyPageService { User editUserName(Long userId, MyPageRequestDTO.ProfileEditNameReq profileEditNameReq); User editUserEmail(Long userId, MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq); + User editUserPhone(Long userId, MyPageRequestDTO.ProfileEditPhoneReq profileEditPhoneReq); + + User editUserPassword(Long userId, MyPageRequestDTO.ProfileEditPasswordReq profileEditPasswordReq); } diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index be7b5d5..7b0d75d 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -24,6 +24,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -48,6 +49,8 @@ public class MyPageServiceImpl implements MyPageService{ private final JwtTokenProvider jwtTokenProvider; private final S3Service s3Service; + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + @Override public void checkPost(Boolean flag) { if (!flag) { @@ -116,5 +119,26 @@ public User editUserEmail(Long userId, MyPageRequestDTO.ProfileEditEmailReq prof return user; } + @Override + public User editUserPhone(Long userId, MyPageRequestDTO.ProfileEditPhoneReq profileEditPhoneReq) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + user.setPhone(profileEditPhoneReq.getPhone()); + return user; + } + + @Override + public User editUserPassword(Long userId, MyPageRequestDTO.ProfileEditPasswordReq profileEditPasswordReq) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + if (!encoder.matches(profileEditPasswordReq.getCurPassword(), user.getPassword())){ + throw new GeneralException(ErrorStatus.PASSWORD_INCORRECT); + } + if (!profileEditPasswordReq.getChangePassword().equals(profileEditPasswordReq.getCheckPassword())){ + throw new GeneralException(ErrorStatus.PASSWORD_CHECK_INCORRECT); + } + String encode = encoder.encode(profileEditPasswordReq.getChangePassword()); + user.setPassword(encode); + return user; + } + } diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index b2d0fac..34c93e6 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -157,4 +157,42 @@ public ApiResponse editUserEmail( User editUserEmail = myPageService.editUserEmail(userId, profileEditEmailReq); return ApiResponse.onSuccess(MyPageConverter.toProfileEditEmailResDTO(editUserEmail)); } + + @PatchMapping(value = "/profile/modify/phone") + @Operation(summary = "회원정보 번호 수정 API", description = "회원정보 번호를 수정하는 API입니다. ex) /user/my-page/profile/modify/phone") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005",description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") + }) + public ApiResponse editUserEmail( + @RequestHeader(name = "atk") String atk, + HttpServletRequest request, + @RequestBody @Valid MyPageRequestDTO.ProfileEditPhoneReq profileEditPhoneReq){ + Long userId = jwtTokenService.JwtToId(request); + emailService.CheckAuthNum(profileEditPhoneReq.getEmail(), profileEditPhoneReq.getCertification()); + User editUserPhone = myPageService.editUserPhone(userId, profileEditPhoneReq); + return ApiResponse.onSuccess(MyPageConverter.toProfileEditPhoneResDTO(editUserPhone)); + } + + @PatchMapping(value = "/profile/modify/password") + @Operation(summary = "회원정보 비밀번호 수정 API", description = "회원정보 비밀번호를 수정하는 API입니다. ex) /user/my-page/profile/modify/password") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4008",description = "NOT_FOUND, 비밀번호가 틀렸습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4009",description = "NOT_FOUND, 확인 비밀번호가 일치하지 않습니다."), + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") + }) + public ApiResponse editUserEmail( + @RequestHeader(name = "atk") String atk, + HttpServletRequest request, + @RequestBody @Valid MyPageRequestDTO.ProfileEditPasswordReq profileEditPasswordReq){ + Long userId = jwtTokenService.JwtToId(request); + User editUserPassword = myPageService.editUserPassword(userId, profileEditPasswordReq); + return ApiResponse.onSuccess(MyPageConverter.toProfileEditPasswordResDTO(editUserPassword)); + } } diff --git a/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java b/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java index d72805c..362d85b 100644 --- a/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java @@ -35,4 +35,27 @@ public static class ProfileEditEmailReq{ private String certification; String changeEmail; } -} + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ProfileEditPhoneReq{ + @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 + //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 + @NotEmpty(message = "이메일을 입력해 주세요") + private String email; + private String certification; + String phone; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ProfileEditPasswordReq{ + String curPassword; + String changePassword; + String checkPassword; + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index 7815fab..09396cd 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -75,4 +75,20 @@ public static class ProfileEditNameRes{ public static class ProfileEditEmailRes{ String changeEmail; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ProfileEditPhoneRes{ + String phone; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ProfileEditPasswordRes{ + String changePassword; + } } From 55aa0a14935d7770336d3d6dd697e9b84a5df913 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Wed, 14 Feb 2024 13:51:31 +0900 Subject: [PATCH 177/255] =?UTF-8?q?#123=20Feat=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95(=EB=B3=B4=EC=95=88=20?= =?UTF-8?q?=EB=A9=94=EC=9D=BC=20=EB=B3=80=EA=B2=BD)=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84,=20Inquiry=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1,=20=EB=AC=B8=EC=9D=98=ED=95=98=EA=B8=B0=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/MyPageConverter.java | 15 +++++++ .../java/friend/spring/domain/Inquiry.java | 31 +++++++++++++ src/main/java/friend/spring/domain/User.java | 4 ++ .../spring/domain/enums/InquiryCategory.java | 5 +++ .../friend/spring/domain/enums/RoleType.java | 2 +- .../spring/repository/InquiryRepository.java | 7 +++ .../friend/spring/service/MyPageService.java | 4 ++ .../spring/service/MyPageServiceImpl.java | 32 ++++++++++++-- .../web/controller/MyPageRestController.java | 44 ++++++++++++++++++- .../spring/web/dto/MyPageRequestDTO.java | 26 +++++++++++ .../spring/web/dto/MyPageResponseDTO.java | 8 ++++ 11 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 src/main/java/friend/spring/domain/Inquiry.java create mode 100644 src/main/java/friend/spring/domain/enums/InquiryCategory.java create mode 100644 src/main/java/friend/spring/repository/InquiryRepository.java diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index eafb923..15aeb34 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -1,6 +1,7 @@ package friend.spring.converter; import friend.spring.domain.Category; +import friend.spring.domain.Inquiry; import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.mapping.Post_scrap; @@ -99,4 +100,18 @@ public static MyPageResponseDTO.ProfileEditPasswordRes toProfileEditPasswordResD .changePassword(user.getPassword()) .build(); } + + public static Inquiry toInquiry(MyPageRequestDTO.MyInquiryReq myInquiryReq, User user){ + return Inquiry.builder() + .category(myInquiryReq.getInquiryCategory()) + .content(myInquiryReq.getContent()) + .user(user) + .build(); + } + + public static MyPageResponseDTO.MyInquiryRes toMyInquiryRes(Inquiry inquiry){ + return MyPageResponseDTO.MyInquiryRes.builder() + .inquiry_id(inquiry.getId()) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/Inquiry.java b/src/main/java/friend/spring/domain/Inquiry.java new file mode 100644 index 0000000..326aadf --- /dev/null +++ b/src/main/java/friend/spring/domain/Inquiry.java @@ -0,0 +1,31 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import friend.spring.domain.enums.InquiryCategory; +import lombok.*; + +import javax.persistence.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Inquiry extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private InquiryCategory category; + + @Column(nullable = false, length = 1000) + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + +} diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index b2d243d..1eca1a7 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -119,6 +119,10 @@ public class User extends BaseEntity implements UserDetails { @OneToMany(mappedBy = "user") private List gaugeVoteList = new ArrayList<>(); + @Builder.Default + @OneToMany(mappedBy = "user") + private List InquiryList = new ArrayList<>(); + @OneToOne(mappedBy = "user") @JoinColumn(name = "file_id") private File file; diff --git a/src/main/java/friend/spring/domain/enums/InquiryCategory.java b/src/main/java/friend/spring/domain/enums/InquiryCategory.java new file mode 100644 index 0000000..118fb94 --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/InquiryCategory.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum InquiryCategory { + ONE, TWO, THREE, FOUR +} diff --git a/src/main/java/friend/spring/domain/enums/RoleType.java b/src/main/java/friend/spring/domain/enums/RoleType.java index 1b713e2..2c645e8 100644 --- a/src/main/java/friend/spring/domain/enums/RoleType.java +++ b/src/main/java/friend/spring/domain/enums/RoleType.java @@ -1,5 +1,5 @@ package friend.spring.domain.enums; public enum RoleType { - USER + USER, ADMIN } diff --git a/src/main/java/friend/spring/repository/InquiryRepository.java b/src/main/java/friend/spring/repository/InquiryRepository.java new file mode 100644 index 0000000..8812c0f --- /dev/null +++ b/src/main/java/friend/spring/repository/InquiryRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.Inquiry; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface InquiryRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/service/MyPageService.java b/src/main/java/friend/spring/service/MyPageService.java index 3235fdc..ed1a384 100644 --- a/src/main/java/friend/spring/service/MyPageService.java +++ b/src/main/java/friend/spring/service/MyPageService.java @@ -1,6 +1,7 @@ package friend.spring.service; import friend.spring.domain.Category; +import friend.spring.domain.Inquiry; import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.mapping.Post_scrap; @@ -29,4 +30,7 @@ public interface MyPageService { User editUserPhone(Long userId, MyPageRequestDTO.ProfileEditPhoneReq profileEditPhoneReq); User editUserPassword(Long userId, MyPageRequestDTO.ProfileEditPasswordReq profileEditPasswordReq); + User editUserSecurity(Long userId, MyPageRequestDTO.ProfileEditSecurityReq profileEditSecurityReq); + + Inquiry createInquiry(Long userId, MyPageRequestDTO.MyInquiryReq myInquiryReq); } diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index beb8084..4ff416a 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -4,10 +4,7 @@ import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.apiPayload.handler.PostHandler; import friend.spring.converter.MyPageConverter; -import friend.spring.domain.Category; -import friend.spring.domain.File; -import friend.spring.domain.Post; -import friend.spring.domain.User; +import friend.spring.domain.*; import friend.spring.domain.enums.S3ImageType; import friend.spring.domain.mapping.Post_scrap; import friend.spring.repository.*; @@ -46,6 +43,7 @@ public class MyPageServiceImpl implements MyPageService{ private final FileRepository fileRepository; private final JwtTokenProvider jwtTokenProvider; private final S3Service s3Service; + private final InquiryRepository inquiryRepository; BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @@ -120,6 +118,12 @@ public User editUserName(Long userId, MyPageRequestDTO.ProfileEditNameReq profil @Override public User editUserEmail(Long userId, MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq) { User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + List all = userRepository.findAll(); + all.forEach(eachUser -> { + if (eachUser.getEmail().equals(profileEditEmailReq.getChangeEmail())) { + throw new GeneralException(ErrorStatus.USER_EXISTS_EMAIL); + } + }); user.setEmail(profileEditEmailReq.getChangeEmail()); return user; } @@ -145,5 +149,25 @@ public User editUserPassword(Long userId, MyPageRequestDTO.ProfileEditPasswordRe return user; } + @Override + public User editUserSecurity(Long userId, MyPageRequestDTO.ProfileEditSecurityReq profileEditSecurityReq) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + List all = userRepository.findAll(); + all.forEach(eachUser -> { + if (eachUser.getEmail().equals(profileEditSecurityReq.getChangeEmail())) { + throw new GeneralException(ErrorStatus.USER_EXISTS_EMAIL); + } + }); + user.setEmail(profileEditSecurityReq.getChangeEmail()); + return user; + } + + @Override + public Inquiry createInquiry(Long userId, MyPageRequestDTO.MyInquiryReq myInquiryReq) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + Inquiry inquiry = MyPageConverter.toInquiry(myInquiryReq, user); + return inquiryRepository.save(inquiry); + } + } diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index fdd8e05..b010d6e 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -4,6 +4,7 @@ import friend.spring.converter.CommentConverter; import friend.spring.converter.MyPageConverter; import friend.spring.domain.Category; +import friend.spring.domain.Inquiry; import friend.spring.domain.Post; import friend.spring.domain.User; import friend.spring.domain.mapping.Comment_choice; @@ -167,7 +168,7 @@ public ApiResponse editUserEmail( @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) - public ApiResponse editUserEmail( + public ApiResponse editUserPhone( @RequestHeader(name = "atk") String atk, HttpServletRequest request, @RequestBody @Valid MyPageRequestDTO.ProfileEditPhoneReq profileEditPhoneReq){ @@ -187,7 +188,7 @@ public ApiResponse editUserEmail( @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) - public ApiResponse editUserEmail( + public ApiResponse editUserPassword( @RequestHeader(name = "atk") String atk, HttpServletRequest request, @RequestBody @Valid MyPageRequestDTO.ProfileEditPasswordReq profileEditPasswordReq){ @@ -195,4 +196,43 @@ public ApiResponse editUserEmail( User editUserPassword = myPageService.editUserPassword(userId, profileEditPasswordReq); return ApiResponse.onSuccess(MyPageConverter.toProfileEditPasswordResDTO(editUserPassword)); } + + @PatchMapping(value = "/profile/modify/security") + @Operation(summary = "회원정보 보안 메일 수정 API", description = "회원정보 보안 메일을 수정하는 API입니다. ex) /user/my-page/profile/modify/security") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4002", description = "이미 존재하는 메일 주소입니다.") + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") + }) + public ApiResponse editUserSecurity( + @RequestHeader(name = "atk") String atk, + HttpServletRequest request, + @RequestBody @Valid MyPageRequestDTO.ProfileEditSecurityReq profileEditSecurityReq){ + Long userId = jwtTokenService.JwtToId(request); + emailService.CheckAuthNum(profileEditSecurityReq.getCurEmail(), profileEditSecurityReq.getCertification()); + emailService.CheckAuthNum(profileEditSecurityReq.getChangeEmail(), profileEditSecurityReq.getNxtCertification()); + User editUserSecurity = myPageService.editUserSecurity(userId, profileEditSecurityReq); + return ApiResponse.onSuccess(MyPageConverter.toProfileEditEmailResDTO(editUserSecurity)); + } + + @PatchMapping(value = "/inquiry") + @Operation(summary = "설정 문의하기 API", description = "문의를 작성하는 API입니다. ex) /user/my-page/inquiry") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4007", description = "최소 5자 이상, 30자 미만 입력해 주세요."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4008", description = "최소 5자 이상, 1000자 미만 입력해 주세요.") + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") + }) + public ApiResponse editUserSecurity( + @RequestHeader(name = "atk") String atk, + HttpServletRequest request, + @RequestBody @Valid MyPageRequestDTO.MyInquiryReq myInquiryReq){ + Long userId = jwtTokenService.JwtToId(request); + Inquiry inquiry = myPageService.createInquiry(userId, myInquiryReq); + return ApiResponse.onSuccess(MyPageConverter.toMyInquiryRes(inquiry)); + } } diff --git a/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java b/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java index 362d85b..f01470c 100644 --- a/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java @@ -1,5 +1,6 @@ package friend.spring.web.dto; +import friend.spring.domain.enums.InquiryCategory; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -58,4 +59,29 @@ public static class ProfileEditPasswordReq{ String changePassword; String checkPassword; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ProfileEditSecurityReq{ + @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 + //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 + @NotEmpty(message = "이메일을 입력해 주세요") + private String curEmail; + private String certification; + @Email + @NotEmpty(message = "이메일을 입력해 주세요") + String changeEmail; + String nxtCertification; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class MyInquiryReq{ + InquiryCategory inquiryCategory; + String content; + } } \ No newline at end of file diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index 09396cd..f850b12 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -91,4 +91,12 @@ public static class ProfileEditPhoneRes{ public static class ProfileEditPasswordRes{ String changePassword; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class MyInquiryRes{ + Long inquiry_id; + } } From f91a7ffa60d056d6127ba984f1a4ac91cb95af18 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 15 Feb 2024 14:56:29 +0900 Subject: [PATCH 178/255] =?UTF-8?q?#113=20Refactor:=20=EA=B0=80=EC=9E=A5?= =?UTF-8?q?=20=ED=95=AB=ED=95=9C=20=EA=B3=A0=EB=AF=BC=ED=88=AC=ED=91=9C=20?= =?UTF-8?q?=EC=9E=84=EC=8B=9C=EB=A1=9C=207=EC=9D=BC=20=EC=9D=B4=EB=82=B4?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/repository/PostRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index 02ca5a1..30ce950 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -20,7 +20,7 @@ public interface PostRepository extends JpaRepository { Page findByPostTypeAndStateAndCategory(PostType postType, PostState state,Category category,Pageable pageable); Page findByUserIdAndPostTypeAndState(Long userId, PostType postType, PostState state, Pageable pageable); Page findAllByUser(User user, PageRequest pageRequest); - @Query(value = "SELECT * FROM post WHERE post.created_at >= DATE_ADD(now(), INTERVAL -24 HOUR) ORDER BY post.point DESC", nativeQuery = true) + @Query(value = "SELECT * FROM post WHERE post.created_at >= DATE_ADD(now(), INTERVAL -7 DAY) ORDER BY post.point DESC", nativeQuery = true) Page findBestPosts(Pageable pageable); Page findAllByOrderByCreatedAtDesc(Pageable pageable); } From 6da6129c90fbe93839b495a9cca67a4e7395f12f Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 15 Feb 2024 18:41:18 +0900 Subject: [PATCH 179/255] =?UTF-8?q?#113=20Refactor:=20=ED=99=88=20?= =?UTF-8?q?=EA=B3=A0=EB=AF=BC=EA=B8=80=20=EB=A6=AC=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=ED=9B=84=EB=B3=B4=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80,=20=EA=B2=8C=EC=9D=B4=EC=A7=80=20=EA=B0=92=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/converter/CandidateConverter.java | 6 ++++++ src/main/java/friend/spring/converter/PostConverter.java | 2 ++ src/main/java/friend/spring/service/PostServiceImpl.java | 4 +++- .../java/friend/spring/web/dto/CandidateResponseDTO.java | 1 + src/main/java/friend/spring/web/dto/PostResponseDTO.java | 1 + 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/converter/CandidateConverter.java b/src/main/java/friend/spring/converter/CandidateConverter.java index 666b38f..62e4a9d 100644 --- a/src/main/java/friend/spring/converter/CandidateConverter.java +++ b/src/main/java/friend/spring/converter/CandidateConverter.java @@ -6,9 +6,15 @@ public class CandidateConverter { public static CandidateResponseDTO.CandidateSummaryRes toCandidateSummaryRes(Candidate candidate, Double percent) { + String candidate_image = null; + if (candidate.getFile() != null) { + candidate_image = candidate.getFile().getUrl(); + } + return CandidateResponseDTO.CandidateSummaryRes.builder() .candidate_id(candidate.getId()) .candidate_name(candidate.getName()) + .candidate_image(candidate_image) .ratio(percent) .build(); } diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 73bec37..7ea6e35 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -784,6 +784,7 @@ public static PostResponseDTO.PostLikeRes toPostLikeRes(Post_like post_like) { public static PostResponseDTO.PostSummaryListRes toPostSummaryRes(Post post, Integer like_cnt, Integer comment_cnt, String postVoteType, List candidateSummaryResList, + Integer gauge, Long general_poll_id, Long gauge_poll_id, Long card_poll_id ) { return PostResponseDTO.PostSummaryListRes.builder() @@ -799,6 +800,7 @@ public static PostResponseDTO.PostSummaryListRes toPostSummaryRes(Post post, Int .general_poll_id(general_poll_id) .gauge_poll_id(gauge_poll_id) .card_poll_id(card_poll_id) + .gauge(gauge) .candidateList(candidateSummaryResList) .build(); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index fdf5c65..44401e3 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -427,6 +427,7 @@ public List getPostRes(Page postPage) Long general_poll_id = null; Long gauge_poll_id = null; Long card_poll_id = null; + Integer gauge = null; List candidateList = null; List candidateSummaryResList = null; @@ -456,6 +457,7 @@ public List getPostRes(Page postPage) } else if (post.getVoteType().equals(GAUGE)) { postVoteType = "GAUGE"; gauge_poll_id = post.getGaugePoll().getId(); + gauge = post.getGaugePoll().getGauge(); } else { postVoteType = "CARD"; card_poll_id = post.getCardPoll().getId(); @@ -479,7 +481,7 @@ public List getPostRes(Page postPage) } } - PostResponseDTO.PostSummaryListRes postGetRes = PostConverter.toPostSummaryRes(post, like_cnt, comment_cnt, postVoteType, candidateSummaryResList, general_poll_id, gauge_poll_id, card_poll_id); + PostResponseDTO.PostSummaryListRes postGetRes = PostConverter.toPostSummaryRes(post, like_cnt, comment_cnt, postVoteType, candidateSummaryResList, gauge, general_poll_id, gauge_poll_id, card_poll_id); return postGetRes; }) .filter(Objects::nonNull) // null인 요소는 필터링 diff --git a/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java b/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java index 13b52a2..999f16e 100644 --- a/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java @@ -12,6 +12,7 @@ public class CandidateResponseDTO { public static class CandidateSummaryRes { Long candidate_id; // 후보 아이디 String candidate_name; // 후보 이름 + String candidate_image; // 후보 이미지 Double ratio; // 비율 } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 457c84b..90672b5 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -142,6 +142,7 @@ public static class PostSummaryListRes { Long general_poll_id; Long gauge_poll_id; Long card_poll_id; + Integer gauge; List candidateList; } From 8e65ea76c658687577caf86882b39a23e2ab84de Mon Sep 17 00:00:00 2001 From: park sang woo Date: Thu, 15 Feb 2024 21:01:36 +0900 Subject: [PATCH 180/255] =?UTF-8?q?=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EC=9E=AC=EC=84=A4=EC=A0=95=20=EC=9D=B8=EC=A6=9DAPI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/service/EmailService.java | 2 +- .../spring/service/PasswordEmailService.java | 86 +++++++++++++++++++ .../web/controller/UserRestController.java | 27 ++++++ .../friend/spring/web/dto/UserRequestDTO.java | 26 ++++++ 4 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 src/main/java/friend/spring/service/PasswordEmailService.java diff --git a/src/main/java/friend/spring/service/EmailService.java b/src/main/java/friend/spring/service/EmailService.java index fd67df6..acdcf58 100644 --- a/src/main/java/friend/spring/service/EmailService.java +++ b/src/main/java/friend/spring/service/EmailService.java @@ -1,6 +1,5 @@ package friend.spring.service; -import friend.spring.apiPayload.GeneralException; import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.apiPayload.handler.UserHandler; import friend.spring.config.RedisUtil; @@ -84,4 +83,5 @@ public void mailSend(String setFrom, String toMail, String title, String content } + } \ No newline at end of file diff --git a/src/main/java/friend/spring/service/PasswordEmailService.java b/src/main/java/friend/spring/service/PasswordEmailService.java new file mode 100644 index 0000000..3d6409d --- /dev/null +++ b/src/main/java/friend/spring/service/PasswordEmailService.java @@ -0,0 +1,86 @@ +package friend.spring.service; + +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.apiPayload.handler.UserHandler; +import friend.spring.config.RedisUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.util.Random; + +@Service +@RequiredArgsConstructor +public class PasswordEmailService { + + @Autowired + private final JavaMailSender emailSender; + @Autowired + private RedisUtil redisUtil; + private int authNumber; + + // 인증코드 체크 + public boolean CheckAuthNum(String email,String authNum){ + if(redisUtil.getData(authNum)==null){ + System.out.println("false1"); + throw new UserHandler(ErrorStatus.INCORRECT_CODE); + } + else if(redisUtil.getData(authNum).equals(email)){ + System.out.println("true"); + return true; + } + else{ + System.out.println("false2"); + throw new UserHandler(ErrorStatus.INCORRECT_CODE); + } + } + //임의의 6자리 인증 코드생성 + public void makeRandomNumber() { + Random r = new Random(); + String randomNumber = ""; + for(int i = 0; i < 6; i++) { + randomNumber += Integer.toString(r.nextInt(10)); + } + + authNumber = Integer.parseInt(randomNumber); + } + //mail을 어디서 보내는지, 어디로 보내는지 , 인증 번호를 html 형식으로 어떻게 보내는지 작성 + public String joinEmail(String email) { + makeRandomNumber(); + String setFrom = "gominchingu@gmail.com"; // email-config에 설정한 자신의 이메일 주소를 입력 + String toMail = email; + String title = "고민친구 비밀번호 재설정 인증 이메일 입니다."; // 이메일 제목 + String content = + "고민친구를 방문해주셔서 감사합니다." + //html 형식으로 작성 ! + "

" + + "비밀번호 재설정 인증 번호는 " + authNumber + "입니다." + + "
" + + "인증 번호의 유효시간은 5분 입니다."; //이메일 내용 삽입 + mailSend(setFrom, toMail, title, content); + + return Integer.toString(authNumber); + } + //이메일을 전송합니다. + public void mailSend(String setFrom, String toMail, String title, String content) { + MimeMessage message = emailSender.createMimeMessage();//JavaMailSender 객체를 사용하여 MimeMessage 객체를 생성 + try { + MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8");//이메일 메시지와 관련된 설정을 수행합니다. + // true를 전달하여 multipart 형식의 메시지를 지원하고, "utf-8"을 전달하여 문자 인코딩을 설정 + helper.setFrom(setFrom);//이메일의 발신자 주소 설정 + helper.setTo(toMail);//이메일의 수신자 주소 설정 + helper.setSubject(title);//이메일의 제목을 설정 + helper.setText(content,true);//이메일의 내용 설정 두 번째 매개 변수에 true를 설정하여 html 설정으로한다. + emailSender.send(message); + } catch (MessagingException e) {//이메일 서버에 연결할 수 없거나, 잘못된 이메일 주소를 사용하거나, 인증 오류가 발생하는 등 오류 + // 이러한 경우 MessagingException이 발생 + e.printStackTrace();//e.printStackTrace()는 예외를 기본 오류 스트림에 출력하는 메서드 + } + redisUtil.setDataExpire(Integer.toString(authNumber),toMail,60*5L); + + } + +} diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index c4dca64..e030830 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -16,6 +16,9 @@ import friend.spring.web.dto.UserRequestDTO; import friend.spring.web.dto.UserResponseDTO; import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; @@ -86,6 +89,30 @@ public ApiResponse join(@RequestBody @Valid UserR return ApiResponse.onSuccess(UserConverter.joinResultDTO(user)); } + @PostMapping ("/passwordMailSend")//비밀번호 재설정 인증 코드 전송 + @Operation(summary = "비밀번호 재설정 인증 코드 전송 API",description = "비밀번호 재설정 인증 코드 전송하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + }) + @Parameters({ }) + public ApiResponse mailSend(@RequestBody @Valid UserRequestDTO.PasswordEmailSendReq emailDto){ + System.out.println("비밀번호 재설정 인증 요청이 들어옴"); + System.out.println("비밀번호 재설정 인증 이메일 :"+emailDto.getEmail()); + + String code = mailService.joinEmail(emailDto.getEmail()); + return ApiResponse.onSuccess(UserConverter.toEmailSendRes(code)); + } + @PostMapping("/passwordMailauthCheck")//이메일 코드 확인 + @Operation(summary = "비밀번호 재설정 코드 확인 API",description = "비밀번호 재설정 코드 확인하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005",description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), + }) + @Parameters({ }) + public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.PasswordEmailSendCheckReq emailSendCheckReq){ + mailService.CheckAuthNum(emailSendCheckReq.getEmail(), emailSendCheckReq.getAuthNum()); + return ApiResponse.onSuccess(null); + } } diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 5bbd203..81835c3 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -98,4 +98,30 @@ public static class EmailSendCheckReq { private String email; private String authNum; } + + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Setter + public static class PasswordEmailSendReq { + @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 + //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 + @NotEmpty(message = "이메일을 입력해 주세요") + private String name; + private String email; + + } + + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Setter + public static class PasswordEmailSendCheckReq { + @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 + //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 + @NotEmpty(message = "이메일을 입력해 주세요") + private String name; + private String email; + private String authNum; + } } From 26e64835f702261b6df6609e6aed180054d45fdf Mon Sep 17 00:00:00 2001 From: park sang woo Date: Thu, 15 Feb 2024 22:01:43 +0900 Subject: [PATCH 181/255] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=9C=84=EC=B9=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response => OAuth}/KakaoProfile.java | 2 +- .../dto/response => OAuth}/OAuthToken.java | 2 +- .../provider/KakaoAuthProvider.java | 10 +++--- .../spring/converter/UserConverter.java | 5 +-- .../spring/domain/enums/SocialType.java | 5 +++ .../kakao/controller/AuthController.java | 36 ------------------- .../spring/kakao/converter/AuthConverter.java | 36 ------------------- .../spring/kakao/domain/enums/SocialType.java | 5 --- .../{kakao => }/service/AuthService.java | 2 +- .../{kakao => }/service/AuthServiceImpl.java | 17 +++------ .../web/controller/UserRestController.java | 15 ++++++-- src/main/resources/application.yml | 2 +- 12 files changed, 32 insertions(+), 105 deletions(-) rename src/main/java/friend/spring/{kakao/dto/response => OAuth}/KakaoProfile.java (92%) rename src/main/java/friend/spring/{kakao/dto/response => OAuth}/OAuthToken.java (86%) rename src/main/java/friend/spring/{kakao => OAuth}/provider/KakaoAuthProvider.java (92%) create mode 100644 src/main/java/friend/spring/domain/enums/SocialType.java delete mode 100644 src/main/java/friend/spring/kakao/controller/AuthController.java delete mode 100644 src/main/java/friend/spring/kakao/converter/AuthConverter.java delete mode 100644 src/main/java/friend/spring/kakao/domain/enums/SocialType.java rename src/main/java/friend/spring/{kakao => }/service/AuthService.java (82%) rename src/main/java/friend/spring/{kakao => }/service/AuthServiceImpl.java (82%) diff --git a/src/main/java/friend/spring/kakao/dto/response/KakaoProfile.java b/src/main/java/friend/spring/OAuth/KakaoProfile.java similarity index 92% rename from src/main/java/friend/spring/kakao/dto/response/KakaoProfile.java rename to src/main/java/friend/spring/OAuth/KakaoProfile.java index 065d6bc..1ea73f6 100644 --- a/src/main/java/friend/spring/kakao/dto/response/KakaoProfile.java +++ b/src/main/java/friend/spring/OAuth/KakaoProfile.java @@ -1,4 +1,4 @@ -package friend.spring.kakao.dto.response; +package friend.spring.OAuth; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Getter; diff --git a/src/main/java/friend/spring/kakao/dto/response/OAuthToken.java b/src/main/java/friend/spring/OAuth/OAuthToken.java similarity index 86% rename from src/main/java/friend/spring/kakao/dto/response/OAuthToken.java rename to src/main/java/friend/spring/OAuth/OAuthToken.java index 36143da..1bfd95c 100644 --- a/src/main/java/friend/spring/kakao/dto/response/OAuthToken.java +++ b/src/main/java/friend/spring/OAuth/OAuthToken.java @@ -1,4 +1,4 @@ -package friend.spring.kakao.dto.response; +package friend.spring.OAuth; import lombok.Data; diff --git a/src/main/java/friend/spring/kakao/provider/KakaoAuthProvider.java b/src/main/java/friend/spring/OAuth/provider/KakaoAuthProvider.java similarity index 92% rename from src/main/java/friend/spring/kakao/provider/KakaoAuthProvider.java rename to src/main/java/friend/spring/OAuth/provider/KakaoAuthProvider.java index a38a669..905864f 100644 --- a/src/main/java/friend/spring/kakao/provider/KakaoAuthProvider.java +++ b/src/main/java/friend/spring/OAuth/provider/KakaoAuthProvider.java @@ -1,18 +1,16 @@ -package friend.spring.kakao.provider; +package friend.spring.OAuth.provider; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import friend.spring.apiPayload.GeneralException; import friend.spring.apiPayload.code.status.ErrorStatus; -import friend.spring.kakao.dto.response.KakaoProfile; -import friend.spring.kakao.dto.response.OAuthToken; +import friend.spring.OAuth.KakaoProfile; +import friend.spring.OAuth.OAuthToken; import friend.spring.security.PrincipalDetailService; import org.springframework.beans.factory.annotation.Value; import friend.spring.repository.UserRepository; import friend.spring.security.JwtTokenProvider; import lombok.RequiredArgsConstructor; -import org.springframework.boot.autoconfigure.cache.CacheProperties; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -34,7 +32,7 @@ public class KakaoAuthProvider { @Value("${kakao.auth.client}") private String client; - @Value("${kakao.auth.redirect-uri}") + @Value("${kakao.auth.redirect_uri}") private String redirect; @Value("${kakao.auth.secret_key}") diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index d621c92..7425b24 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -2,7 +2,7 @@ import friend.spring.domain.*; import friend.spring.domain.enums.Gender; -import friend.spring.kakao.dto.response.KakaoProfile; +import friend.spring.OAuth.KakaoProfile; import friend.spring.web.dto.*; import friend.spring.domain.enums.RoleType; @@ -204,4 +204,5 @@ public static User KakaoUser( .email(kakaoProfile.getKakao_account().getEmail()).build(); } -} \ No newline at end of file + +} diff --git a/src/main/java/friend/spring/domain/enums/SocialType.java b/src/main/java/friend/spring/domain/enums/SocialType.java new file mode 100644 index 0000000..f7de7d9 --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/SocialType.java @@ -0,0 +1,5 @@ +package friend.spring.domain.enums; + +public enum SocialType { + KAKAO +} diff --git a/src/main/java/friend/spring/kakao/controller/AuthController.java b/src/main/java/friend/spring/kakao/controller/AuthController.java deleted file mode 100644 index 222b0d7..0000000 --- a/src/main/java/friend/spring/kakao/controller/AuthController.java +++ /dev/null @@ -1,36 +0,0 @@ -package friend.spring.kakao.controller; - -import friend.spring.apiPayload.ApiResponse; -import friend.spring.apiPayload.GeneralException; -import friend.spring.kakao.service.AuthService; -import friend.spring.service.JwtTokenService; -import friend.spring.service.UserService; -import friend.spring.web.dto.TokenDTO; -import friend.spring.web.dto.UserResponseDTO; -//import io.swagger.annotations.ApiResponse; -import org.springframework.web.bind.annotation.*; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.Operation; -import lombok.RequiredArgsConstructor; - -import java.util.List; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/auth") -public class AuthController { - - private final AuthService authService; - private final JwtTokenService jwtTokenService; - private final UserService userService; - - @Operation(summary = "카카오 로그인 API", description = "카카오 로그인 및 회원 가입을 진행") - @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), - }) - @GetMapping("/login/kakao") - public ApiResponse> kakaoLogin(@RequestParam("code") String code) throws GeneralException { - - return ApiResponse.onSuccess(authService.kakaoLogin(code)); - } -} diff --git a/src/main/java/friend/spring/kakao/converter/AuthConverter.java b/src/main/java/friend/spring/kakao/converter/AuthConverter.java deleted file mode 100644 index 5fc9278..0000000 --- a/src/main/java/friend/spring/kakao/converter/AuthConverter.java +++ /dev/null @@ -1,36 +0,0 @@ -package friend.spring.kakao.converter; - -import friend.spring.domain.User; -import friend.spring.domain.enums.RoleType; -import friend.spring.kakao.dto.response.KakaoProfile; -import friend.spring.web.dto.TokenDTO; -import friend.spring.web.dto.UserResponseDTO; - -public class AuthConverter { - - public static User kakaoUser(KakaoProfile kakaoProfile) { - return User.builder() - .nickname(kakaoProfile.getProperties().getNickname()) - .email(kakaoProfile.getKakao_account().getEmail()) - .role(RoleType.USER) - .build(); - } - - public static UserResponseDTO.OAuthResponse toOAuthResponse( - TokenDTO accessToken, TokenDTO refreshToken,Boolean isLogin, User user) { - return UserResponseDTO.OAuthResponse.builder() - .refreshToken(refreshToken) - .accessToken(accessToken) - .isLogin(isLogin) - .email(user.getEmail()) - .build(); - } - -// public static AuthResponseDTO.TokenRefreshResponse toTokenRefreshResponse( -// TokenDTO accessToken, TokenDTO refreshToken) { -// return AuthResponseDTO.TokenRefreshResponse.builder() -// .accessToken(accessToken) -// .refreshToken(refreshToken) -// .build(); -// } -} diff --git a/src/main/java/friend/spring/kakao/domain/enums/SocialType.java b/src/main/java/friend/spring/kakao/domain/enums/SocialType.java deleted file mode 100644 index 9371e30..0000000 --- a/src/main/java/friend/spring/kakao/domain/enums/SocialType.java +++ /dev/null @@ -1,5 +0,0 @@ -package friend.spring.kakao.domain.enums; - -public enum SocialType { - KAKAO -} diff --git a/src/main/java/friend/spring/kakao/service/AuthService.java b/src/main/java/friend/spring/service/AuthService.java similarity index 82% rename from src/main/java/friend/spring/kakao/service/AuthService.java rename to src/main/java/friend/spring/service/AuthService.java index f1e2682..05cd6b3 100644 --- a/src/main/java/friend/spring/kakao/service/AuthService.java +++ b/src/main/java/friend/spring/service/AuthService.java @@ -1,4 +1,4 @@ -package friend.spring.kakao.service; +package friend.spring.service; import friend.spring.web.dto.TokenDTO; diff --git a/src/main/java/friend/spring/kakao/service/AuthServiceImpl.java b/src/main/java/friend/spring/service/AuthServiceImpl.java similarity index 82% rename from src/main/java/friend/spring/kakao/service/AuthServiceImpl.java rename to src/main/java/friend/spring/service/AuthServiceImpl.java index 921c97e..c7b795b 100644 --- a/src/main/java/friend/spring/kakao/service/AuthServiceImpl.java +++ b/src/main/java/friend/spring/service/AuthServiceImpl.java @@ -1,22 +1,15 @@ -package friend.spring.kakao.service; +package friend.spring.service; -import friend.spring.apiPayload.ApiResponse; -import friend.spring.apiPayload.GeneralException; -import friend.spring.apiPayload.handler.UserHandler; import friend.spring.converter.UserConverter; import friend.spring.domain.User; -import friend.spring.kakao.dto.response.KakaoProfile; -import friend.spring.kakao.dto.response.OAuthToken; -import friend.spring.kakao.provider.KakaoAuthProvider; +import friend.spring.OAuth.KakaoProfile; +import friend.spring.OAuth.OAuthToken; +import friend.spring.OAuth.provider.KakaoAuthProvider; import friend.spring.repository.UserRepository; import friend.spring.security.JwtTokenProvider; -import friend.spring.service.UserService; import friend.spring.web.dto.TokenDTO; -import friend.spring.web.dto.UserRequestDTO; -import friend.spring.web.dto.UserResponseDTO; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.HttpStatus; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; @@ -26,8 +19,6 @@ import java.util.Optional; import java.util.concurrent.TimeUnit; -import static friend.spring.apiPayload.code.status.ErrorStatus.*; - @Service @RequiredArgsConstructor public class AuthServiceImpl implements AuthService { diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index ffe43ff..3397d36 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -7,20 +7,19 @@ import friend.spring.domain.Level; import friend.spring.domain.Post; import friend.spring.domain.User; +import friend.spring.service.AuthService; import friend.spring.repository.UserRepository; import friend.spring.service.CommentService; import friend.spring.service.EmailService; import friend.spring.service.PostService; import friend.spring.service.UserService; import friend.spring.service.*; -import friend.spring.web.dto.AlarmResponseDTO; import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; import friend.spring.web.dto.UserResponseDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.annotations.Api; import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -42,7 +41,7 @@ public class UserRestController { private final PostService postService; private final CommentService commentService; private final JwtTokenService jwtTokenService; - + private final AuthService authService; //마이 페이지 조회 @GetMapping("/my-page") @@ -215,5 +214,15 @@ public ApiResponse myPoint(@RequestHeader("atk") S Integer point = userService.pointCheck(userId); return ApiResponse.onSuccess(UserConverter.toPointViewResDTO(point)); } + + @Operation(summary = "카카오 로그인 API", description = "카카오 로그인 및 회원 가입을 진행") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + }) + @GetMapping("/login/kakao") + public ApiResponse> kakaoLogin(@RequestParam("code") String code) throws GeneralException { + + return ApiResponse.onSuccess(authService.kakaoLogin(code)); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f5af034..810ba09 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -65,6 +65,6 @@ mail: kakao: auth: client: 58d29ff7378109a321d4edc551a773c2 - redirect-uri: http://localhost:3000/api/auth/callback/kakao + redirect_uri: http://localhost:3000/api/auth/callback/kakao secret_key: OSzm4b9sGFMZ982joQAkhZ7Fpiph4eOY From be44f600ae0471117b8b915197eab3d1855457bf Mon Sep 17 00:00:00 2001 From: park sang woo Date: Thu, 15 Feb 2024 22:21:15 +0900 Subject: [PATCH 182/255] =?UTF-8?q?=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 810ba09..b25bdb6 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -64,7 +64,7 @@ mail: password: ${gmail.password} kakao: auth: - client: 58d29ff7378109a321d4edc551a773c2 - redirect_uri: http://localhost:3000/api/auth/callback/kakao - secret_key: OSzm4b9sGFMZ982joQAkhZ7Fpiph4eOY + client: ${KAKAO_AUTH_CLIENT} + redirect-uri: ${KAKAO_AUTH_REDIRECT_URI} + secret_key: ${KAKAO_AUTH_SECRET_KEY} From ec28b99e24f036c7409c86d530e8eeecb9e9431a Mon Sep 17 00:00:00 2001 From: ls-rain Date: Thu, 15 Feb 2024 23:36:13 +0900 Subject: [PATCH 183/255] =?UTF-8?q?#127=20Feat=20:=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=ED=95=9C=20=EA=B2=8C=EC=8B=9C=EB=AC=BC(=EB=82=B4=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC)=20=EC=83=81=EC=84=B8=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/MyPageConverter.java | 22 +++++++++++++++++++ .../spring/repository/PostRepository.java | 6 +++++ .../friend/spring/service/MyPageService.java | 3 +++ .../spring/service/MyPageServiceImpl.java | 14 ++++++++++++ .../web/controller/MyPageRestController.java | 22 +++++++++++++++++++ .../spring/web/dto/MyPageResponseDTO.java | 19 ++++++++++++++++ 6 files changed, 86 insertions(+) diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index 15aeb34..e081af8 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -114,4 +114,26 @@ public static MyPageResponseDTO.MyInquiryRes toMyInquiryRes(Inquiry inquiry){ .inquiry_id(inquiry.getId()) .build(); } + + public static MyPageResponseDTO.SavedPostCategoryDetailRes toSavedPostCategoryDetailRes(Post post){ + long diffTime = post.getCreatedAt().until(LocalDateTime.now(), ChronoUnit.SECONDS); // now보다 이후면 +, 전이면 - + diffTime = diffTime / SECOND; + diffTime = diffTime / MINUTE; + diffTime = diffTime / HOUR; + return MyPageResponseDTO.SavedPostCategoryDetailRes.builder() + .ago(diffTime) + .title(post.getTitle()) + .content(post.getContent()) + .postLike(post.getPostLikeList().size()) + .comment(post.getCommentList().size()) + .build(); + } + + public static MyPageResponseDTO.SavedPostCategoryDetailListRes toSavedPostCategoryDetailListRes(Page postList, Category category){ + List postCategoryDetailResList = postList.stream().map(MyPageConverter::toSavedPostCategoryDetailRes).collect(Collectors.toList()); + return MyPageResponseDTO.SavedPostCategoryDetailListRes.builder() + .name(category.getName()) + .postList(postCategoryDetailResList) + .build(); + } } diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index 30ce950..ddeeea8 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -4,6 +4,7 @@ import friend.spring.domain.Post; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; +import io.lettuce.core.dynamic.annotation.Param; import org.springframework.data.domain.Page; import friend.spring.domain.User; import org.springframework.data.domain.Page; @@ -23,4 +24,9 @@ public interface PostRepository extends JpaRepository { @Query(value = "SELECT * FROM post WHERE post.created_at >= DATE_ADD(now(), INTERVAL -7 DAY) ORDER BY post.point DESC", nativeQuery = true) Page findBestPosts(Pageable pageable); Page findAllByOrderByCreatedAtDesc(Pageable pageable); + + @Query(value = "SELECT * FROM post p join post_scrap ps ON p.user_id = ps.user_id join category c on p.category_id = c.id", nativeQuery = true) + Page findCategoryDetail(@Param("user_id") Long userId, + @Param("category_id") Long categoryId, + PageRequest pageRequest); } diff --git a/src/main/java/friend/spring/service/MyPageService.java b/src/main/java/friend/spring/service/MyPageService.java index ed1a384..f550174 100644 --- a/src/main/java/friend/spring/service/MyPageService.java +++ b/src/main/java/friend/spring/service/MyPageService.java @@ -33,4 +33,7 @@ public interface MyPageService { User editUserSecurity(Long userId, MyPageRequestDTO.ProfileEditSecurityReq profileEditSecurityReq); Inquiry createInquiry(Long userId, MyPageRequestDTO.MyInquiryReq myInquiryReq); + Page getCategoryDetailList(Long userId, Long categoryId, Integer page); + + Category getCategory(Long categoryId); } diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index 4ff416a..ad6aac4 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -169,5 +169,19 @@ public Inquiry createInquiry(Long userId, MyPageRequestDTO.MyInquiryReq myInquir return inquiryRepository.save(inquiry); } + @Override + public Page getCategoryDetailList(Long userId, Long categoryId, Integer page) { + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + Category category = categoryRepository.findById(categoryId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_CATGORY_NOT_FOUND)); + Page detailList = postRepository.findCategoryDetail(userId, categoryId, PageRequest.of(page, 10)); + return detailList; + } + + @Override + public Category getCategory(Long categoryId) { + Category category = categoryRepository.findById(categoryId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_CATGORY_NOT_FOUND)); + return category; + } + } diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index b010d6e..4309fd0 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -235,4 +235,26 @@ public ApiResponse editUserSecurity( Inquiry inquiry = myPageService.createInquiry(userId, myInquiryReq); return ApiResponse.onSuccess(MyPageConverter.toMyInquiryRes(inquiry)); } + + @GetMapping(value = "/post/{category-id}") + @Operation(summary = "사용자 글 카테고리 상세보기 조회 API", description = "카테고리별로 상세화면을 조회하는 API입니다. ex) /user/my-page/post/{category-id}") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), + @Parameter(name = "category-id", description = "path variable - 카테고리 아이디"), + }) + public ApiResponse GetUserCategoryDetail( + @RequestHeader(name = "atk") String atk, + @PathVariable("category-id") Long categoryId, + @RequestParam(name = "page", defaultValue = "0") Integer page, + HttpServletRequest request){ + Long userId = jwtTokenService.JwtToId(request); + Page categoryDetailList = myPageService.getCategoryDetailList(userId, categoryId, page); + Category category = myPageService.getCategory(categoryId); + return ApiResponse.onSuccess(MyPageConverter.toSavedPostCategoryDetailListRes(categoryDetailList, category)); + } } diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index f850b12..609ec99 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -99,4 +99,23 @@ public static class ProfileEditPasswordRes{ public static class MyInquiryRes{ Long inquiry_id; } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class SavedPostCategoryDetailRes{ + Long ago; + String title; + String content; + Integer postLike; + Integer comment; + } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class SavedPostCategoryDetailListRes{ + String name; + List postList; + } } From abe40939b5ff087fcc4454776ce1009787eccd09 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Fri, 16 Feb 2024 11:41:14 +0900 Subject: [PATCH 184/255] =?UTF-8?q?REFACTOR(=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EC=B6=95=EC=86=8C,=20?= =?UTF-8?q?=EC=88=98=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OAuth/provider/KakaoAuthProvider.java | 1 - .../friend/spring/service/EmailService.java | 134 ++++++++++-------- .../spring/service/PasswordEmailService.java | 86 ----------- .../web/controller/UserRestController.java | 2 +- .../friend/spring/web/dto/UserRequestDTO.java | 3 +- 5 files changed, 77 insertions(+), 149 deletions(-) delete mode 100644 src/main/java/friend/spring/service/PasswordEmailService.java diff --git a/src/main/java/friend/spring/OAuth/provider/KakaoAuthProvider.java b/src/main/java/friend/spring/OAuth/provider/KakaoAuthProvider.java index 905864f..1c6ee33 100644 --- a/src/main/java/friend/spring/OAuth/provider/KakaoAuthProvider.java +++ b/src/main/java/friend/spring/OAuth/provider/KakaoAuthProvider.java @@ -27,7 +27,6 @@ public class KakaoAuthProvider { private final PrincipalDetailService principalDetailService; private final UserRepository userRepository; private final JwtTokenProvider jwtTokenProvider; -// private final RefreshTokenService refreshTokenService; @Value("${kakao.auth.client}") private String client; diff --git a/src/main/java/friend/spring/service/EmailService.java b/src/main/java/friend/spring/service/EmailService.java index acdcf58..e8ec00e 100644 --- a/src/main/java/friend/spring/service/EmailService.java +++ b/src/main/java/friend/spring/service/EmailService.java @@ -17,71 +17,87 @@ @RequiredArgsConstructor public class EmailService { - @Autowired - private final JavaMailSender emailSender; - @Autowired - private RedisUtil redisUtil; - private int authNumber; + @Autowired + private final JavaMailSender emailSender; + @Autowired + private RedisUtil redisUtil; + private int authNumber; - // 인증코드 체크 - public boolean CheckAuthNum(String email,String authNum){ - if(redisUtil.getData(authNum)==null){ - System.out.println("false1"); - throw new UserHandler(ErrorStatus.INCORRECT_CODE); - } - else if(redisUtil.getData(authNum).equals(email)){ - System.out.println("true"); - return true; - } - else{ - System.out.println("false2"); - throw new UserHandler(ErrorStatus.INCORRECT_CODE); - } + // 인증코드 체크 + public boolean CheckAuthNum(String email, String authNum) { + if (redisUtil.getData(authNum) == null) { + System.out.println("false1"); + throw new UserHandler(ErrorStatus.INCORRECT_CODE); + } else if (redisUtil.getData(authNum).equals(email)) { + System.out.println("true"); + return true; + } else { + System.out.println("false2"); + throw new UserHandler(ErrorStatus.INCORRECT_CODE); } - //임의의 6자리 인증 코드생성 - public void makeRandomNumber() { - Random r = new Random(); - String randomNumber = ""; - for(int i = 0; i < 6; i++) { - randomNumber += Integer.toString(r.nextInt(10)); - } + } - authNumber = Integer.parseInt(randomNumber); + //임의의 6자리 인증 코드생성 + public void makeRandomNumber() { + Random r = new Random(); + String randomNumber = ""; + for (int i = 0; i < 6; i++) { + randomNumber += Integer.toString(r.nextInt(10)); } - //mail을 어디서 보내는지, 어디로 보내는지 , 인증 번호를 html 형식으로 어떻게 보내는지 작성 - public String joinEmail(String email) { - makeRandomNumber(); - String setFrom = "gominchingu@gmail.com"; // email-config에 설정한 자신의 이메일 주소를 입력 - String toMail = email; - String title = "고민친구 회원 가입 인증 이메일 입니다."; // 이메일 제목 - String content = - "고민친구를 방문해주셔서 감사합니다." + //html 형식으로 작성 ! - "

" + - "인증 번호는 " + authNumber + "입니다." + - "
" + - "인증 코드의 유효시간은 5분 입니다."; //이메일 내용 삽입 - mailSend(setFrom, toMail, title, content); - return Integer.toString(authNumber); - } - //이메일을 전송합니다. - public void mailSend(String setFrom, String toMail, String title, String content) { - MimeMessage message = emailSender.createMimeMessage();//JavaMailSender 객체를 사용하여 MimeMessage 객체를 생성 - try { - MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8");//이메일 메시지와 관련된 설정을 수행합니다. - // true를 전달하여 multipart 형식의 메시지를 지원하고, "utf-8"을 전달하여 문자 인코딩을 설정 - helper.setFrom(setFrom);//이메일의 발신자 주소 설정 - helper.setTo(toMail);//이메일의 수신자 주소 설정 - helper.setSubject(title);//이메일의 제목을 설정 - helper.setText(content,true);//이메일의 내용 설정 두 번째 매개 변수에 true를 설정하여 html 설정으로한다. - emailSender.send(message); - } catch (MessagingException e) {//이메일 서버에 연결할 수 없거나, 잘못된 이메일 주소를 사용하거나, 인증 오류가 발생하는 등 오류 - // 이러한 경우 MessagingException이 발생 - e.printStackTrace();//e.printStackTrace()는 예외를 기본 오류 스트림에 출력하는 메서드 - } - redisUtil.setDataExpire(Integer.toString(authNumber),toMail,60*5L); + authNumber = Integer.parseInt(randomNumber); + } + + //mail을 어디서 보내는지, 어디로 보내는지 , 인증 번호를 html 형식으로 어떻게 보내는지 작성 + public String joinEmail(String email) { + makeRandomNumber(); + String setFrom = "gominchingu@gmail.com"; // email-config에 설정한 자신의 이메일 주소를 입력 + String toMail = email; + String title = "고민친구 회원 가입 인증 이메일 입니다."; // 이메일 제목 + String content = + "고민친구를 방문해주셔서 감사합니다." + //html 형식으로 작성 ! + "

" + + "인증 번호는 " + authNumber + "입니다." + + "
" + + "인증 코드의 유효시간은 5분 입니다."; //이메일 내용 삽입 + mailSend(setFrom, toMail, title, content); + return Integer.toString(authNumber); + } + + //이메일을 전송합니다. + public void mailSend(String setFrom, String toMail, String title, String content) { + MimeMessage message = emailSender.createMimeMessage();//JavaMailSender 객체를 사용하여 MimeMessage 객체를 생성 + try { + MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");//이메일 메시지와 관련된 설정을 수행합니다. + // true를 전달하여 multipart 형식의 메시지를 지원하고, "utf-8"을 전달하여 문자 인코딩을 설정 + helper.setFrom(setFrom);//이메일의 발신자 주소 설정 + helper.setTo(toMail);//이메일의 수신자 주소 설정 + helper.setSubject(title);//이메일의 제목을 설정 + helper.setText(content, true);//이메일의 내용 설정 두 번째 매개 변수에 true를 설정하여 html 설정으로한다. + emailSender.send(message); + } catch (MessagingException e) {//이메일 서버에 연결할 수 없거나, 잘못된 이메일 주소를 사용하거나, 인증 오류가 발생하는 등 오류 + // 이러한 경우 MessagingException이 발생 + e.printStackTrace();//e.printStackTrace()는 예외를 기본 오류 스트림에 출력하는 메서드 } + redisUtil.setDataExpire(Integer.toString(authNumber), toMail, 60 * 5L); + + } + //mail을 어디서 보내는지, 어디로 보내는지 , 인증 번호를 html 형식으로 어떻게 보내는지 작성 + public String passwordEmail(String email) { + makeRandomNumber(); + String setFrom = "gominchingu@gmail.com"; // email-config에 설정한 자신의 이메일 주소를 입력 + String toMail = email; + String title = "고민친구 비밀번호 재설정 인증 이메일 입니다."; // 이메일 제목 + String content = + "고민친구를 방문해주셔서 감사합니다." + //html 형식으로 작성 ! + "

" + + "인증 번호는 " + authNumber + "입니다." + + "
" + + "인증 코드의 유효시간은 5분 입니다."; //이메일 내용 삽입 + mailSend(setFrom, toMail, title, content); - } \ No newline at end of file + return Integer.toString(authNumber); + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/service/PasswordEmailService.java b/src/main/java/friend/spring/service/PasswordEmailService.java deleted file mode 100644 index 3d6409d..0000000 --- a/src/main/java/friend/spring/service/PasswordEmailService.java +++ /dev/null @@ -1,86 +0,0 @@ -package friend.spring.service; - -import friend.spring.apiPayload.code.status.ErrorStatus; -import friend.spring.apiPayload.handler.UserHandler; -import friend.spring.config.RedisUtil; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.MimeMessageHelper; -import org.springframework.stereotype.Service; - -import javax.mail.MessagingException; -import javax.mail.internet.MimeMessage; -import java.util.Random; - -@Service -@RequiredArgsConstructor -public class PasswordEmailService { - - @Autowired - private final JavaMailSender emailSender; - @Autowired - private RedisUtil redisUtil; - private int authNumber; - - // 인증코드 체크 - public boolean CheckAuthNum(String email,String authNum){ - if(redisUtil.getData(authNum)==null){ - System.out.println("false1"); - throw new UserHandler(ErrorStatus.INCORRECT_CODE); - } - else if(redisUtil.getData(authNum).equals(email)){ - System.out.println("true"); - return true; - } - else{ - System.out.println("false2"); - throw new UserHandler(ErrorStatus.INCORRECT_CODE); - } - } - //임의의 6자리 인증 코드생성 - public void makeRandomNumber() { - Random r = new Random(); - String randomNumber = ""; - for(int i = 0; i < 6; i++) { - randomNumber += Integer.toString(r.nextInt(10)); - } - - authNumber = Integer.parseInt(randomNumber); - } - //mail을 어디서 보내는지, 어디로 보내는지 , 인증 번호를 html 형식으로 어떻게 보내는지 작성 - public String joinEmail(String email) { - makeRandomNumber(); - String setFrom = "gominchingu@gmail.com"; // email-config에 설정한 자신의 이메일 주소를 입력 - String toMail = email; - String title = "고민친구 비밀번호 재설정 인증 이메일 입니다."; // 이메일 제목 - String content = - "고민친구를 방문해주셔서 감사합니다." + //html 형식으로 작성 ! - "

" + - "비밀번호 재설정 인증 번호는 " + authNumber + "입니다." + - "
" + - "인증 번호의 유효시간은 5분 입니다."; //이메일 내용 삽입 - mailSend(setFrom, toMail, title, content); - - return Integer.toString(authNumber); - } - //이메일을 전송합니다. - public void mailSend(String setFrom, String toMail, String title, String content) { - MimeMessage message = emailSender.createMimeMessage();//JavaMailSender 객체를 사용하여 MimeMessage 객체를 생성 - try { - MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8");//이메일 메시지와 관련된 설정을 수행합니다. - // true를 전달하여 multipart 형식의 메시지를 지원하고, "utf-8"을 전달하여 문자 인코딩을 설정 - helper.setFrom(setFrom);//이메일의 발신자 주소 설정 - helper.setTo(toMail);//이메일의 수신자 주소 설정 - helper.setSubject(title);//이메일의 제목을 설정 - helper.setText(content,true);//이메일의 내용 설정 두 번째 매개 변수에 true를 설정하여 html 설정으로한다. - emailSender.send(message); - } catch (MessagingException e) {//이메일 서버에 연결할 수 없거나, 잘못된 이메일 주소를 사용하거나, 인증 오류가 발생하는 등 오류 - // 이러한 경우 MessagingException이 발생 - e.printStackTrace();//e.printStackTrace()는 예외를 기본 오류 스트림에 출력하는 메서드 - } - redisUtil.setDataExpire(Integer.toString(authNumber),toMail,60*5L); - - } - -} diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 3397d36..e60ea98 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -147,7 +147,7 @@ public ApiResponse mailSend(@RequestBody @Valid Us System.out.println("비밀번호 재설정 인증 요청이 들어옴"); System.out.println("비밀번호 재설정 인증 이메일 :"+emailDto.getEmail()); - String code = mailService.joinEmail(emailDto.getEmail()); + String code = mailService.passwordEmail(emailDto.getEmail()); return ApiResponse.onSuccess(UserConverter.toEmailSendRes(code)); } @PostMapping("/passwordMailauthCheck")//이메일 코드 확인 diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index a52bfef..59a910c 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -106,9 +106,8 @@ public static class PasswordEmailSendReq { @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 @NotEmpty(message = "이메일을 입력해 주세요") - private String name; private String email; - + private String name; } @NoArgsConstructor From 2c1ec2895859246bc183800ade5118f7252fed8f Mon Sep 17 00:00:00 2001 From: park sang woo Date: Fri, 16 Feb 2024 11:48:12 +0900 Subject: [PATCH 185/255] =?UTF-8?q?=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EC=9E=AC=EC=84=A4=EC=A0=95=20=EC=9D=B8=EC=A6=9D=20=EC=9E=AC?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/web/dto/UserRequestDTO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 59a910c..ad34e4f 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -118,8 +118,8 @@ public static class PasswordEmailSendCheckReq { @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 @NotEmpty(message = "이메일을 입력해 주세요") - private String name; private String email; + private String name; private String authNum; } } From fbd94747f4249484c7e8dcaf8487569978e51637 Mon Sep 17 00:00:00 2001 From: hjh Date: Fri, 16 Feb 2024 15:41:11 +0900 Subject: [PATCH 186/255] =?UTF-8?q?#133=20=EA=B8=80=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0,=20=EA=B3=A0=EB=AF=BC=EA=B8=80=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=EB=B3=B4=EA=B8=B0=EC=8B=9C=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 381 ++++++++++++++++-- .../spring/web/dto/PostResponseDTO.java | 4 + 2 files changed, 348 insertions(+), 37 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 22927ed..a71671c 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -568,6 +568,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, File userFile=null; String userImg=null; Optional userFileOptional=Optional.ofNullable(post.getUser().getFile()); + List userVotePercent=null; + List topCandidatePercent=null; + List allCandidatePercent=null; if(userFileOptional.isPresent()){ userFile = userFileOptional.get(); @@ -588,27 +591,172 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); List userChoiceList=null; + List topCandidateList=null; Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); Boolean engage=false; if(post.getVoteType()==PostVoteType.GENERAL) { - List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - if(!post.getGeneralPoll().getGeneralVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()){ - engage=true; + List pollOptionDTOList = post.getGeneralPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); + if (!post.getGeneralPoll().getGeneralVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { + engage = true; + } +//일반 투표 마감 전 + if (post.getGeneralPoll().getDeadline().isAfter(LocalDateTime.now())) { + if (engage) { + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); + // 총 투표수 계산 + long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + //1등 투표 계산 + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .max(); + + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + topCandidateList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + + topCandidatePercent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) + .postVoteType(PostVoteType.GENERAL) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + + } + return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) + .postVoteType(PostVoteType.GENERAL) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .pollOption(pollOptionDTOList) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); } - if(engage) { - //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(cardVote -> cardVote.getUser().getId().equals(userId)) - .flatMap(cardVote -> cardVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); +//일반 투표 마감 후 + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); + // 총 투표수 계산 + long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + //1등 투표 계산 + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .max(); + + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + topCandidateList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + + topCandidatePercent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + allCandidatePercent=post.getGeneralPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId=candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + if (engage) { return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) .postVoteType(PostVoteType.GENERAL) @@ -618,7 +766,11 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) .userVote(userChoiceList) + .userVotePercent(userVotePercent) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) .like(likeCount) .comment(commentCount) .isLike(isLike) @@ -635,17 +787,37 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollOption(pollOptionDTOList) + .allCandidatePercent(allCandidatePercent) .like(likeCount) .comment(commentCount) .isLike(isLike) .isComment(isComment) .build(); + + } - if(post.getVoteType()==PostVoteType.GAUGE){ - if(!post.getGaugePoll().getGaugeVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()){ - engage=true; + if(post.getVoteType()==PostVoteType.GAUGE) { + if (!post.getGaugePoll().getGaugeVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { + engage = true; } - if(engage) { + if (post.getGaugePoll().getDeadline().isAfter(LocalDateTime.now())) { + if (engage) { + return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) + .postVoteType(PostVoteType.GAUGE) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .pollTitle(post.getGaugePoll().getPollTitle()) + .gauge(post.getGaugePoll().getGauge()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + } return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) .postVoteType(PostVoteType.GAUGE) @@ -655,44 +827,174 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollTitle(post.getGaugePoll().getPollTitle()) - .gauge(post.getGaugePoll().getGauge()) .like(likeCount) .comment(commentCount) .isLike(isLike) .isComment(isComment) .build(); } + + } + List pollOptionDTOList = post.getCardPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); + if (!post.getCardPoll().getCardVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { + engage = true; + } +//일반 투표 마감 전 + if (post.getCardPoll().getDeadline().isAfter(LocalDateTime.now())) { + if (engage) { + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); + // 총 투표수 계산 + long totalVotes = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + //1등 투표 계산 + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .max(); + + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + topCandidateList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + + topCandidatePercent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + return PostResponseDTO.PollPostGetResponse.builder() + .postId(post.getId()) + .postVoteType(PostVoteType.CARD) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + + } return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) - .postVoteType(PostVoteType.GAUGE) + .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) .userImg(userImg) .title(post.getTitle()) .content(post.getContent()) .uploadDate(post.getCreatedAt()) - .pollTitle(post.getGaugePoll().getPollTitle()) + .pollOption(pollOptionDTOList) .like(likeCount) .comment(commentCount) .isLike(isLike) .isComment(isComment) .build(); } - List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - if(!post.getCardPoll().getCardVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()){ - engage=true; - } - if(engage) { - //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() - .filter(cardVote -> cardVote.getUser().getId().equals(userId)) - .flatMap(cardVote -> cardVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getCardPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - +//일반 투표 마감 후 + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); + // 총 투표수 계산 + long totalVotes = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + //1등 투표 계산 + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble highestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .max(); + + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> entry.getValue() == highestCandidate.getAsDouble() * totalVotes) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + topCandidateList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + + topCandidatePercent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + allCandidatePercent=post.getCardPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId=candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + if (engage) { return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) .postVoteType(PostVoteType.CARD) @@ -702,7 +1004,11 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) .userVote(userChoiceList) + .userVotePercent(userVotePercent) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) .like(likeCount) .comment(commentCount) .isLike(isLike) @@ -719,6 +1025,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollOption(pollOptionDTOList) + .allCandidatePercent(allCandidatePercent) .like(likeCount) .comment(commentCount) .isLike(isLike) diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 986af31..683eb83 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -76,7 +76,11 @@ public static class PollPostGetResponse{ String content; LocalDateTime uploadDate; List pollOption; + List topCandidate; List userVote; + List userVotePercent; + List topCandidatePercent; + List allCandidatePercent; String pollTitle; //게이지투표만 해당(게이지 투표 이름) Integer gauge; Integer like; From d5784779794d9942b57a7a2299b850040170d496 Mon Sep 17 00:00:00 2001 From: hjh Date: Fri, 16 Feb 2024 16:17:16 +0900 Subject: [PATCH 187/255] =?UTF-8?q?#133=20=EA=B8=80=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0,=20=EA=B3=A0=EB=AF=BC=EA=B8=80=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=EB=B3=B4=EA=B8=B0=EC=8B=9C=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/PostConverter.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 21e1f15..efd2c6b 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -835,12 +835,14 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } } + System.out.println("여기서??????"); List pollOptionDTOList = post.getCardPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); + System.out.println("!!!!!!!!!!!!!여기아님!!!!!!!!!!!!!!!!!"); if (!post.getCardPoll().getCardVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { engage = true; } -//일반 투표 마감 전 +//카드 투표 마감 전 if (post.getCardPoll().getDeadline().isAfter(LocalDateTime.now())) { if (engage) { //투표한 후보에 대한 정보 @@ -932,7 +934,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .isComment(isComment) .build(); } -//일반 투표 마감 후 +//카드 투표 마감 후 //투표한 후보에 대한 정보 Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() .filter(cardVote -> cardVote.getUser().getId().equals(userId)) From 6f4ca16f31c7bf937a67a6be2cd7d408eba2109c Mon Sep 17 00:00:00 2001 From: hjh Date: Fri, 16 Feb 2024 18:11:24 +0900 Subject: [PATCH 188/255] =?UTF-8?q?#133=20=EA=B3=A0=EB=AF=BC=EA=B8=80=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=EB=B3=B4=EA=B8=B0=EC=8B=9C=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=EC=97=90=20=EB=A7=9E=EA=B2=8C=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 68 ++++++++++++++++++- .../spring/service/VoteServiceImpl.java | 6 +- .../spring/web/dto/PostResponseDTO.java | 5 +- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index efd2c6b..9b3aa18 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -659,6 +659,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, }) .collect(Collectors.toList()); return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(true) + .isVoted(true) .postId(post.getId()) .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) @@ -680,6 +682,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(true) + .isVoted(false) .postId(post.getId()) .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) @@ -758,6 +762,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .collect(Collectors.toList()); if (engage) { return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(false) + .isVoted(true) .postId(post.getId()) .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) @@ -779,6 +785,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(false) + .isVoted(false) .postId(post.getId()) .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) @@ -800,9 +808,19 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, if (!post.getGaugePoll().getGaugeVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { engage = true; } + OptionaluserGaugeVoteOptional=post.getGaugePoll().getGaugeVoteList().stream() + .filter(gaugeVote -> gaugeVote.getUser().getId().equals(userId)) + .findFirst(); + Integer userGauge=null; + if(userGaugeVoteOptional.isPresent()){ + userGauge=userGaugeVoteOptional.get().getValue(); + } if (post.getGaugePoll().getDeadline().isAfter(LocalDateTime.now())) { if (engage) { + return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(true) + .isVoted(true) .postId(post.getId()) .postVoteType(PostVoteType.GAUGE) .nickname(post.getUser().getNickname()) @@ -811,7 +829,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollTitle(post.getGaugePoll().getPollTitle()) - .gauge(post.getGaugePoll().getGauge()) + .userGauge(userGauge) + .totalGauge(post.getGaugePoll().getGauge()) .like(likeCount) .comment(commentCount) .isLike(isLike) @@ -819,6 +838,26 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .build(); } return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(true) + .isVoted(false) + .postId(post.getId()) + .postVoteType(PostVoteType.GAUGE) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .pollTitle(post.getGaugePoll().getPollTitle()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + } + if (engage) { + return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(false) + .isVoted(true) .postId(post.getId()) .postVoteType(PostVoteType.GAUGE) .nickname(post.getUser().getNickname()) @@ -827,12 +866,31 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollTitle(post.getGaugePoll().getPollTitle()) + .userGauge(userGauge) + .totalGauge(post.getGaugePoll().getGauge()) .like(likeCount) .comment(commentCount) .isLike(isLike) .isComment(isComment) .build(); } + return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(false) + .isVoted(false) + .postId(post.getId()) + .postVoteType(PostVoteType.GAUGE) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .pollTitle(post.getGaugePoll().getPollTitle()) + .totalGauge(post.getGaugePoll().getGauge()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); } System.out.println("여기서??????"); @@ -899,6 +957,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, }) .collect(Collectors.toList()); return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(true) + .isVoted(true) .postId(post.getId()) .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) @@ -920,6 +980,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(true) + .isVoted(false) .postId(post.getId()) .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) @@ -998,6 +1060,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .collect(Collectors.toList()); if (engage) { return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(false) + .isVoted(true) .postId(post.getId()) .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) @@ -1019,6 +1083,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } return PostResponseDTO.PollPostGetResponse.builder() + .onGoing(false) + .isVoted(false) .postId(post.getId()) .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index 595dcb9..cc7543d 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -108,9 +108,9 @@ public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long Post gaugePost=optionalPost.get(); Integer currentGauge=gaugePost.getGaugePoll().getGauge(); Integer engagedUser=gaugePost.getGaugePoll().getGaugeVoteList().size(); - gaugePost.getGaugePoll().setGauge((currentGauge+request.getValue())/engagedUser); - - + int result1=(int)Math.round((currentGauge*(engagedUser-1.0)+value)/(engagedUser)); + Integer result=(Integer)result1; + gaugePost.getGaugePoll().setGauge(result); return gaugeVoteRepository.save(newGaugeVote); } @Override diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index e58139c..d1e4ea6 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -68,6 +68,8 @@ public static class PollPostGetListDTO{ @NoArgsConstructor @AllArgsConstructor public static class PollPostGetResponse{ + Boolean onGoing; + Boolean isVoted; Long postId; PostVoteType postVoteType; String nickname; @@ -82,7 +84,8 @@ public static class PollPostGetResponse{ List topCandidatePercent; List allCandidatePercent; String pollTitle; //게이지투표만 해당(게이지 투표 이름) - Integer gauge; + Integer userGauge; + Integer totalGauge; Integer like; Integer comment; Boolean isLike; From d94fae30e93e9170638215d4f6a598e5308adbd7 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Fri, 16 Feb 2024 22:14:17 +0900 Subject: [PATCH 189/255] =?UTF-8?q?#127=20Feat=20:=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=ED=95=9C=20=EA=B2=8C=EC=8B=9C=EB=AC=BC(=EB=82=B4=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC)=20=EC=83=81=EC=84=B8=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/repository/PostRepository.java | 6 ++---- .../friend/spring/web/controller/MyPageRestController.java | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index ddeeea8..3ac3789 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -25,8 +25,6 @@ public interface PostRepository extends JpaRepository { Page findBestPosts(Pageable pageable); Page findAllByOrderByCreatedAtDesc(Pageable pageable); - @Query(value = "SELECT * FROM post p join post_scrap ps ON p.user_id = ps.user_id join category c on p.category_id = c.id", nativeQuery = true) - Page findCategoryDetail(@Param("user_id") Long userId, - @Param("category_id") Long categoryId, - PageRequest pageRequest); + @Query(value = "SELECT p FROM Post p JOIN p.postScrapList s JOIN p.category c WHERE s.user.id = :userId and c.id = :categoryId") + Page findCategoryDetail(Long userId, Long categoryId, PageRequest pageRequest); } diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index 4309fd0..89a3f4c 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -241,6 +241,8 @@ public ApiResponse editUserSecurity( @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004",description = "NOT_FOUND, 글에 대한 스크랩 데이터를 찾을 수 없습니다."), + }) @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), From 89d3c2c05170eac9ecbead6b5e228cdfcca91495 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 16 Feb 2024 23:55:03 +0900 Subject: [PATCH 190/255] =?UTF-8?q?#113=20Feat:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EA=B5=AC=EB=8F=85=20/=20=EB=8C=93=EA=B8=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EC=8B=9C=20=EC=95=8C=EB=A6=BC=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20/=20=ED=99=88-=EC=95=88=20=EC=9D=BD=EC=9D=80=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=A1=B4=EC=9E=AC=20=EC=97=AC=EB=B6=80=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20/=20=EC=95=8C=EB=A6=BC=20=EC=9D=BD=EC=9D=8C=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/AlarmConverter.java | 34 +++++- .../friend/spring/converter/SseConverter.java | 32 ++++++ src/main/java/friend/spring/domain/Alarm.java | 11 ++ .../java/friend/spring/domain/Comment.java | 4 + .../friend/spring/domain/enums/AlarmType.java | 2 +- .../spring/repository/AlarmRepository.java | 2 + .../spring/repository/EmitterRepository.java | 44 ++++++++ .../friend/spring/service/AlarmService.java | 7 ++ .../spring/service/AlarmServiceImpl.java | 35 ++++++ .../spring/service/CommentServiceImpl.java | 42 +++++-- .../friend/spring/service/SseService.java | 104 ++++++++++++++++++ .../web/controller/AlarmRestController.java | 33 ++++++ .../spring/web/controller/SseController.java | 29 +++++ .../spring/web/dto/AlarmResponseDTO.java | 19 +++- .../friend/spring/web/dto/SseResponseDTO.java | 25 +++++ 15 files changed, 407 insertions(+), 16 deletions(-) create mode 100644 src/main/java/friend/spring/converter/SseConverter.java create mode 100644 src/main/java/friend/spring/repository/EmitterRepository.java create mode 100644 src/main/java/friend/spring/service/SseService.java create mode 100644 src/main/java/friend/spring/web/controller/SseController.java create mode 100644 src/main/java/friend/spring/web/dto/SseResponseDTO.java diff --git a/src/main/java/friend/spring/converter/AlarmConverter.java b/src/main/java/friend/spring/converter/AlarmConverter.java index b6044d8..43f2944 100644 --- a/src/main/java/friend/spring/converter/AlarmConverter.java +++ b/src/main/java/friend/spring/converter/AlarmConverter.java @@ -1,6 +1,10 @@ package friend.spring.converter; import friend.spring.domain.Alarm; +import friend.spring.domain.Comment; +import friend.spring.domain.Post; +import friend.spring.domain.User; +import friend.spring.domain.enums.AlarmType; import friend.spring.web.dto.AlarmResponseDTO; import org.springframework.data.domain.Page; @@ -11,10 +15,23 @@ public class AlarmConverter { //알림 public static AlarmResponseDTO.AlarmResDTO toAlarmResDTO(Alarm alarm){ + String userPhoto = null; + if (alarm.getUser().getFile() != null) { + userPhoto = alarm.getUser().getFile().getUrl(); + } + + Long commentId = null; + if (alarm.getComment() != null) { + commentId = alarm.getComment().getId(); + } + return AlarmResponseDTO.AlarmResDTO.builder() - .nickName(alarm.getUser().getNickname()) - .type(alarm.getType()) - .content(alarm.getContent()) + .userNickname(alarm.getUser().getNickname()) + .userPhoto(userPhoto) + .alarmType(alarm.getType().toString()) + .alarmContent(alarm.getContent()) + .postId(alarm.getPost().getId()) + .commentId(commentId) .createdAt(alarm.getCreatedAt()) .build(); } @@ -26,4 +43,15 @@ public static AlarmResponseDTO.AlarmListResDTO toAlarmListResDTO(Page ala .alarmList(alarmResDTOList) .build(); } + + public static Alarm toAlarm(String alarmContent, AlarmType alarmType, Post post, User user, Comment comment) { + return Alarm.builder() + .content(alarmContent) + .type(alarmType) + .post(post) + .user(user) + .comment(comment) + .read(false) + .build(); + } } diff --git a/src/main/java/friend/spring/converter/SseConverter.java b/src/main/java/friend/spring/converter/SseConverter.java new file mode 100644 index 0000000..9b204e3 --- /dev/null +++ b/src/main/java/friend/spring/converter/SseConverter.java @@ -0,0 +1,32 @@ +package friend.spring.converter; + +import friend.spring.domain.Comment; +import friend.spring.domain.enums.AlarmType; +import friend.spring.web.dto.SseResponseDTO; + +public class SseConverter { + public static SseResponseDTO.CommentCreateResDTO toCommentCreateResDTO (Comment comment, AlarmType alarmType) { + String userPhoto = null; + if (comment.getUser().getFile() != null) { + userPhoto = comment.getUser().getFile().getUrl(); + } + + String alarmContent = comment.getUser().getNickname(); + if (alarmType.equals(AlarmType.COMMENT)) { + alarmContent += "님이 회원님의 게시물에 댓글을 남겼습니다."; + } else { + alarmContent += "님이 회원님의 댓글에 답글을 남겼습니다."; + } + + return SseResponseDTO.CommentCreateResDTO.builder() + .userNickname(comment.getUser().getNickname()) + .userPhoto(userPhoto) + .alarmContent(alarmContent) + .commentContent(comment.getContent()) + .createdAt(comment.getCreatedAt()) + .alarmType(AlarmType.COMMENT.toString()) + .postId(comment.getPost().getId()) + .commentId(comment.getId()) + .build(); + } +} diff --git a/src/main/java/friend/spring/domain/Alarm.java b/src/main/java/friend/spring/domain/Alarm.java index 3df230b..883ca40 100644 --- a/src/main/java/friend/spring/domain/Alarm.java +++ b/src/main/java/friend/spring/domain/Alarm.java @@ -30,4 +30,15 @@ public class Alarm extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "post_id") private Post post; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "comment_id") + private Comment comment; + + @Column(nullable = true) + private Boolean read; // 해당 알림 읽었는지 여부 + + public void setRead(Boolean read) { + this.read = read; + } } diff --git a/src/main/java/friend/spring/domain/Comment.java b/src/main/java/friend/spring/domain/Comment.java index ca6823a..52d8ef9 100644 --- a/src/main/java/friend/spring/domain/Comment.java +++ b/src/main/java/friend/spring/domain/Comment.java @@ -54,6 +54,10 @@ public class Comment extends BaseEntity { @OneToMany(mappedBy = "comment") private List commentLikeList = new ArrayList<>(); + @Builder.Default + @OneToMany(mappedBy = "comment") + private List alarmList = new ArrayList<>(); + public void update(String content) { this.content = content; } diff --git a/src/main/java/friend/spring/domain/enums/AlarmType.java b/src/main/java/friend/spring/domain/enums/AlarmType.java index 57e156e..c16f477 100644 --- a/src/main/java/friend/spring/domain/enums/AlarmType.java +++ b/src/main/java/friend/spring/domain/enums/AlarmType.java @@ -1,5 +1,5 @@ package friend.spring.domain.enums; public enum AlarmType { - COMMENT, VOTE_FINISH + COMMENT, REPLY_COMMENT, VOTE_FINISH } diff --git a/src/main/java/friend/spring/repository/AlarmRepository.java b/src/main/java/friend/spring/repository/AlarmRepository.java index 3355c52..4cff38b 100644 --- a/src/main/java/friend/spring/repository/AlarmRepository.java +++ b/src/main/java/friend/spring/repository/AlarmRepository.java @@ -8,4 +8,6 @@ public interface AlarmRepository extends JpaRepository { Page findAllByUser(User user, PageRequest pageRequest); + + Boolean existsByUserIdAndReadIsFalse(Long userId); } diff --git a/src/main/java/friend/spring/repository/EmitterRepository.java b/src/main/java/friend/spring/repository/EmitterRepository.java new file mode 100644 index 0000000..83b6255 --- /dev/null +++ b/src/main/java/friend/spring/repository/EmitterRepository.java @@ -0,0 +1,44 @@ +package friend.spring.repository; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Repository +@RequiredArgsConstructor +public class EmitterRepository { + // 모든 Emitters를 저장하는 ConcurrentHashMap + private final Map emitters = new ConcurrentHashMap<>(); + + /** + * 주어진 아이디와 이미터를 저장 + * + * @param id - 사용자 아이디. + * @param emitter - 이벤트 Emitter. + */ + public void save(Long id, SseEmitter emitter) { + emitters.put(id, emitter); + } + + /** + * 주어진 아이디의 Emitter를 제거 + * + * @param id - 사용자 아이디. + */ + public void deleteById(Long id) { + emitters.remove(id); + } + + /** + * 주어진 아이디의 Emitter를 가져옴. + * + * @param id - 사용자 아이디. + * @return SseEmitter - 이벤트 Emitter. + */ + public SseEmitter get(Long id) { + return emitters.get(id); + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/service/AlarmService.java b/src/main/java/friend/spring/service/AlarmService.java index afc2d86..7fde446 100644 --- a/src/main/java/friend/spring/service/AlarmService.java +++ b/src/main/java/friend/spring/service/AlarmService.java @@ -1,11 +1,18 @@ package friend.spring.service; import friend.spring.domain.Alarm; +import friend.spring.web.dto.AlarmResponseDTO; import org.springframework.data.domain.Page; +import javax.servlet.http.HttpServletRequest; + public interface AlarmService { void checkAlarm(boolean flag); Page getAlarmList(Long userId, Integer page); + + AlarmResponseDTO.AlarmLeftResDTO getRemainingAlarm(HttpServletRequest request); + + void editAlarmRead(Long alarmId, HttpServletRequest request); } diff --git a/src/main/java/friend/spring/service/AlarmServiceImpl.java b/src/main/java/friend/spring/service/AlarmServiceImpl.java index 801a827..5ba7068 100644 --- a/src/main/java/friend/spring/service/AlarmServiceImpl.java +++ b/src/main/java/friend/spring/service/AlarmServiceImpl.java @@ -6,12 +6,15 @@ import friend.spring.domain.User; import friend.spring.repository.AlarmRepository; import friend.spring.repository.UserRepository; +import friend.spring.security.JwtTokenProvider; +import friend.spring.web.dto.AlarmResponseDTO; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.servlet.http.HttpServletRequest; import java.util.Optional; @Service @@ -22,6 +25,7 @@ public class AlarmServiceImpl implements AlarmService{ private final UserRepository userRepository; private final AlarmRepository alarmRepository; private final UserService userService; + private final JwtTokenProvider jwtTokenProvider; @Override public void checkAlarm(boolean flag) { if (!flag){ @@ -41,4 +45,35 @@ public Page getAlarmList(Long userId, Integer page) { return alarmPage; } + + @Override + public AlarmResponseDTO.AlarmLeftResDTO getRemainingAlarm(HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Boolean isAlarmLeft = alarmRepository.existsByUserIdAndReadIsFalse(userId); + return AlarmResponseDTO.AlarmLeftResDTO.builder() + .isAlarmLeft(isAlarmLeft).build(); + } + + @Override + @Transactional + public void editAlarmRead(Long alarmId, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Optional optionalAlarm = alarmRepository.findById(alarmId); + if (optionalAlarm.isEmpty()) { + checkAlarm(false); + } + + Alarm alarm = optionalAlarm.get(); + alarm.setRead(true); + } } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 701c28f..d8ccf0d 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -3,29 +3,26 @@ import friend.spring.apiPayload.GeneralException; import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.apiPayload.handler.CommentHandler; +import friend.spring.converter.AlarmConverter; import friend.spring.converter.CommentConverter; -import friend.spring.domain.Comment; -import friend.spring.domain.Point; -import friend.spring.domain.Post; -import friend.spring.domain.User; +import friend.spring.converter.SseConverter; +import friend.spring.domain.*; +import friend.spring.domain.enums.AlarmType; import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.repository.*; import friend.spring.security.JwtTokenProvider; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; +import friend.spring.web.dto.SseResponseDTO; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import software.amazon.awssdk.services.s3.endpoints.internal.Value; import javax.servlet.http.HttpServletRequest; import java.util.*; -import java.util.stream.Collectors; import static friend.spring.apiPayload.code.status.ErrorStatus.*; @@ -40,9 +37,11 @@ public class CommentServiceImpl implements CommentService { private final CommentLikeRepository commentLikeRepository; private final CommentChoiceRepository commentChoiceRepository; private final PointRepository pointRepository; + private final AlarmRepository alarmRepository; private final UserService userService; private final PostService postService; private final JwtTokenProvider jwtTokenProvider; + private final SseService notificationService; @Override public void checkComment(Boolean flag) { @@ -101,18 +100,43 @@ public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq req User user = optionalUser.get(); // 대댓글인 경우 + boolean isReplyComment = false; if (requestBody.getParentId() != null) { + isReplyComment = true; Optional optionalParentComment = commentRepository.findById(requestBody.getParentId()); if (optionalParentComment.isEmpty()) { this.checkComment(false); } + // 댓글 소속이 글과 일치하는지 확인 + if (!Objects.equals(optionalParentComment.get().getPost().getId(), post.getId())) { + throw new CommentHandler(COMMENT_POST_NOT_MATCH); + } + parentComment = optionalParentComment.get(); } Comment comment = CommentConverter.toComment(requestBody, post, user, parentComment); + commentRepository.save(comment); + + // 알림 ResponseDTO 생성 + SseResponseDTO.CommentCreateResDTO commentCreateResDTO; + + // 필수) 해당 댓글이 있는 글 주인에게 알림 생성 + commentCreateResDTO = SseConverter.toCommentCreateResDTO(comment, AlarmType.COMMENT); + Alarm newAlarm = AlarmConverter.toAlarm(commentCreateResDTO.getAlarmContent(), AlarmType.COMMENT, post, comment.getPost().getUser(), comment); + alarmRepository.save(newAlarm); + notificationService.customNotify(comment.getPost().getUser().getId(), commentCreateResDTO, comment.getContent(), AlarmType.COMMENT.toString()); + + // 옵션) 해당 댓글이 대댓글인 경우, 루트 댓글 주인에게 알림 생성 + if (isReplyComment) { + commentCreateResDTO = SseConverter.toCommentCreateResDTO(comment, AlarmType.REPLY_COMMENT); + newAlarm = AlarmConverter.toAlarm(commentCreateResDTO.getAlarmContent(), AlarmType.REPLY_COMMENT, post, comment.getPost().getUser(), comment); + alarmRepository.save(newAlarm); + notificationService.customNotify(comment.getParentComment().getUser().getId(), commentCreateResDTO, comment.getContent(), AlarmType.REPLY_COMMENT.toString()); + } - return commentRepository.save(comment); + return comment; } @Override diff --git a/src/main/java/friend/spring/service/SseService.java b/src/main/java/friend/spring/service/SseService.java new file mode 100644 index 0000000..8503cfc --- /dev/null +++ b/src/main/java/friend/spring/service/SseService.java @@ -0,0 +1,104 @@ +package friend.spring.service; + +import friend.spring.repository.EmitterRepository; +import friend.spring.security.JwtTokenProvider; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +@Service +@RequiredArgsConstructor +public class SseService { + // 기본 타임아웃 설정 + private static final Long DEFAULT_TIMEOUT = 60L * 1000 * 60; // 1시간 + + private final EmitterRepository emitterRepository; + private final JwtTokenProvider jwtTokenProvider; + + /** + * 클라이언트가 구독을 위해 호출하는 메서드. + * + * @param request - 구독하는 클라이언트의 사용자 atk가 담긴 + * @return SseEmitter - 서버에서 보낸 이벤트 Emitter + */ + public SseEmitter subscribe(HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + SseEmitter emitter = createEmitter(userId); + + sendToClient(userId, "EventStream Created. [userId=" + userId + "]"); + return emitter; + } + + /** + * 서버의 이벤트를 클라이언트에게 보내는 메서드 + * 다른 서비스 로직에서 이 메서드를 사용해 데이터를 Object event에 넣고 전송하면 된다. + * + * @param userId - 메세지를 전송할 사용자의 아이디. + * @param event - 전송할 이벤트 객체. + */ + public void notify(Long userId, Object event) { + sendToClient(userId, event); + } + + public void customNotify(Long userId, T data, String comment, String type) { + sendToClient(userId, data, comment, type); + } + + /** + * 클라이언트에게 데이터를 전송 + * + * @param id - 데이터를 받을 사용자의 아이디. + * @param data - 전송할 데이터. + */ + private void sendToClient(Long id, Object data) { + SseEmitter emitter = emitterRepository.get(id); + if (emitter != null) { + try { + emitter.send(SseEmitter.event() + .id(String.valueOf(id)) + .name("sse") + .data(data)); + } catch (IOException exception) { + emitterRepository.deleteById(id); + emitter.completeWithError(exception); + } + } + } + + private void sendToClient(Long userId, T data, String comment, String type) { + SseEmitter emitter = emitterRepository.get(userId); + if (emitter != null) { + try { + emitter.send(SseEmitter.event() + .id(String.valueOf(userId)) + .name(type) + .data(data) + .comment(comment)); + } catch (IOException e) { + emitterRepository.deleteById(userId); + emitter.completeWithError(e); + } + } + } + + /** + * 사용자 아이디를 기반으로 이벤트 Emitter를 생성 + * + * @param id - 사용자 아이디. + * @return SseEmitter - 생성된 이벤트 Emitter. + */ + private SseEmitter createEmitter(Long id) { + SseEmitter emitter = new SseEmitter(DEFAULT_TIMEOUT); + emitterRepository.save(id, emitter); + + // Emitter가 완료될 때(모든 데이터가 성공적으로 전송된 상태) Emitter를 삭제한다. + emitter.onCompletion(() -> emitterRepository.deleteById(id)); + // Emitter가 타임아웃 되었을 때(지정된 시간동안 어떠한 이벤트도 전송되지 않았을 때) Emitter를 삭제한다. + emitter.onTimeout(() -> emitterRepository.deleteById(id)); + + return emitter; + } +} diff --git a/src/main/java/friend/spring/web/controller/AlarmRestController.java b/src/main/java/friend/spring/web/controller/AlarmRestController.java index b0b26d0..4fe2fc4 100644 --- a/src/main/java/friend/spring/web/controller/AlarmRestController.java +++ b/src/main/java/friend/spring/web/controller/AlarmRestController.java @@ -44,4 +44,37 @@ private ApiResponse getAlarm( Page alarmList = alarmService.getAlarmList(userId, page); return ApiResponse.onSuccess(AlarmConverter.toAlarmListResDTO(alarmList)); } + + // 홈 - 안 읽은 알림 존재 여부 조회 + @GetMapping("/alarm/notReadAlarm") + @Operation(summary = "사용자 알림 조회 API",description = "사용자의 알림 목록을 조회하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공") + }) + @Parameters({}) + private ApiResponse getRemainingAlarm( + @RequestHeader(name = "atk") String atk, + HttpServletRequest request + ){ + return ApiResponse.onSuccess(alarmService.getRemainingAlarm(request)); + } + + // 알림 읽음 처리 + @PatchMapping("/alarm/{alarm-id}") + @Operation(summary = "사용자 알림 읽음 처리 API",description = "사용자의 알림을 읽음 처리하는 API입니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "ALARM4001",description = "NOT_FOUND, 알림을 찾을 수 없습니다."), + }) + @Parameters({ + @Parameter(name = "alarm-id", description = "path variable - 알람 아이디"), + }) + private ApiResponse editAlarmRead( + @PathVariable("alarm-id") Long alarmId, + @RequestHeader(name = "atk") String atk, + HttpServletRequest request + ){ + alarmService.editAlarmRead(alarmId, request); + return ApiResponse.onSuccess(null); + } } diff --git a/src/main/java/friend/spring/web/controller/SseController.java b/src/main/java/friend/spring/web/controller/SseController.java new file mode 100644 index 0000000..a0f8f4d --- /dev/null +++ b/src/main/java/friend/spring/web/controller/SseController.java @@ -0,0 +1,29 @@ +package friend.spring.web.controller; + +import friend.spring.service.SseService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import javax.servlet.http.HttpServletRequest; + +@RestController +@RequestMapping("/sse") +@RequiredArgsConstructor +public class SseController { + private final SseService notificationService; + + @GetMapping(value = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public SseEmitter subscribe( + @RequestHeader(name = "atk") String atk, + HttpServletRequest request + ) { + return notificationService.subscribe(request); + } + + @PostMapping("/send-data/{id}") + public void sendData(@PathVariable Long id) { + notificationService.notify(id, "data"); + } +} diff --git a/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java b/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java index 8d43fb5..899c0f8 100644 --- a/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java @@ -23,9 +23,22 @@ public static class AlarmListResDTO{ @NoArgsConstructor @AllArgsConstructor public static class AlarmResDTO{ - String nickName; - AlarmType type; - String content; + Long alarmId; + String userNickname; + String userPhoto; + String alarmType; + String alarmContent; + String commentContent; + Long postId; + Long commentId; LocalDateTime createdAt; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class AlarmLeftResDTO{ + Boolean isAlarmLeft; + } } diff --git a/src/main/java/friend/spring/web/dto/SseResponseDTO.java b/src/main/java/friend/spring/web/dto/SseResponseDTO.java new file mode 100644 index 0000000..52b9d8c --- /dev/null +++ b/src/main/java/friend/spring/web/dto/SseResponseDTO.java @@ -0,0 +1,25 @@ +package friend.spring.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +public class SseResponseDTO { + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class CommentCreateResDTO { + String userNickname; + String userPhoto; + String alarmType; + String alarmContent; + String commentContent; + Long postId; + Long commentId; + LocalDateTime createdAt; + } +} From 610bf84da26ebcb6ad0474901308060be210f34c Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 17 Feb 2024 00:09:22 +0900 Subject: [PATCH 191/255] =?UTF-8?q?#113=20Refactor:=20=EC=95=8C=EB=A6=BC?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/SseConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/converter/SseConverter.java b/src/main/java/friend/spring/converter/SseConverter.java index 9b204e3..120fd1e 100644 --- a/src/main/java/friend/spring/converter/SseConverter.java +++ b/src/main/java/friend/spring/converter/SseConverter.java @@ -24,7 +24,7 @@ public static SseResponseDTO.CommentCreateResDTO toCommentCreateResDTO (Comment .alarmContent(alarmContent) .commentContent(comment.getContent()) .createdAt(comment.getCreatedAt()) - .alarmType(AlarmType.COMMENT.toString()) + .alarmType(alarmType.toString()) .postId(comment.getPost().getId()) .commentId(comment.getId()) .build(); From 3db5cc8f6253e738e4403e83d8aeb8f4c9c793d7 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 17 Feb 2024 00:22:41 +0900 Subject: [PATCH 192/255] =?UTF-8?q?#113=20Refactor:=20=ED=99=88=20-=20?= =?UTF-8?q?=EC=95=88=20=EC=9D=BD=EC=9D=80=20=EC=95=8C=EB=A6=BC=20=EC=A1=B4?= =?UTF-8?q?=EC=9E=AC=20=EC=97=AC=EB=B6=80=20=EC=A1=B0=ED=9A=8C=20=EC=84=A4?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/web/controller/AlarmRestController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/web/controller/AlarmRestController.java b/src/main/java/friend/spring/web/controller/AlarmRestController.java index 4fe2fc4..6cc6229 100644 --- a/src/main/java/friend/spring/web/controller/AlarmRestController.java +++ b/src/main/java/friend/spring/web/controller/AlarmRestController.java @@ -47,7 +47,7 @@ private ApiResponse getAlarm( // 홈 - 안 읽은 알림 존재 여부 조회 @GetMapping("/alarm/notReadAlarm") - @Operation(summary = "사용자 알림 조회 API",description = "사용자의 알림 목록을 조회하는 API입니다.") + @Operation(summary = "홈 - 안 읽은 알림 존재 여부 조회 API",description = "사용자가 안 읽은 알림이 존재하는지 여부를 조회하는 API입니다.") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공") }) From 50b7d88b620087360e75af9019c552d1fca5fd72 Mon Sep 17 00:00:00 2001 From: hjh Date: Sat, 17 Feb 2024 01:27:34 +0900 Subject: [PATCH 193/255] =?UTF-8?q?#137=20=EA=B3=A0=EB=AF=BC=EA=B8=80=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=EB=B3=B4=EA=B8=B0=EC=8B=9C=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=EC=97=90=20=EB=A7=9E=EA=B2=8C=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 452 ++++++++++++++---- .../spring/web/dto/PostResponseDTO.java | 21 +- 2 files changed, 371 insertions(+), 102 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 9b3aa18..bf2ba95 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -239,9 +239,14 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B Integer commentCount = post.getCommentList().size(); Boolean myPost=false; List userChoiceList=null; - List percent=null; - List voteResult=null; - Integer value=null; + List topCandidateList=null; + List userVotePercent=null; + List topCandidatePercent=null; + List allCandidatePercent=null; + List userVoteResult=null; + List topVoteResult=null; + Integer userGauge=null; + Integer totalGauge=null; Boolean isVote=false; Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); @@ -278,13 +283,23 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B } if(post.getVoteType()==PostVoteType.GAUGE){ //나노초 단위로 마감 여부 확인 + LocalDateTime now = LocalDateTime.now(); long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGaugePoll().getDeadline()); Boolean voteOnGoing = nanosUntilDeadline > 0; //투표에 참여 했을 경우 if(engage){ - value=post.getGaugePoll().getGauge(); + OptionaluserGaugeVoteOptional=post.getGaugePoll().getGaugeVoteList().stream() + .filter(gaugeVote -> gaugeVote.getUser().getId().equals(userId)) + .findFirst(); + if(userGaugeVoteOptional.isPresent()){ + userGauge=userGaugeVoteOptional.get().getValue(); + } isVote=true; + totalGauge=post.getGaugePoll().getGauge(); + } + if(post.getGaugePoll().getDeadline().isBefore(LocalDateTime.now())||myPost){ + totalGauge=post.getGaugePoll().getGauge(); } return PostResponseDTO.PostDetailResponse.builder() .postType(VOTE) @@ -298,7 +313,8 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .isVoted(isVote) .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getGaugePoll().getPollTitle()) - .gauge(value) + .userGauge(userGauge) + .totalGauge(totalGauge) .point(post.getPoint()) .deadline(post.getGaugePoll().getDeadline()) .view(post.getView()) @@ -318,6 +334,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B //투표 후보 리스트 List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); + if(post.getGeneralPoll().getDeadline().isAfter(LocalDateTime.now())){ if(engage) { //투표한 후보에 대한 정보 Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() @@ -347,7 +364,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); // 사용자가 선택한 후보의 선택률 계산 - percent = userSelectedCandidateIds.stream() + userVotePercent = userSelectedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); @@ -355,48 +372,46 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .collect(Collectors.toList()); // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) - voteResult = userSelectedCandidateIds.stream() + userVoteResult = userSelectedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return String.format("%d/%d", selectionCount, totalVotes); }) .collect(Collectors.toList()); isVote=true; - if(myPost){ - // 투표수가 가장 많은 후보의 선택률 계산 - OptionalDouble hightestCandidate = candidateSelectionCounts.values().stream() - .mapToDouble(aLong -> (double) aLong / totalVotes) - .max(); - - // 선택률이 가장 높은 후보의 ID들 찾기 - List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(aLong -> (double) aLong.getValue() / totalVotes) + .max(); - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 - userChoiceList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + topCandidateList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); - percent = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); + topCandidatePercent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); - // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) - voteResult = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return String.format("%d/%d", selectionCount, totalVotes); - }) - .collect(Collectors.toList()); - } + topVoteResult = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); } return PostResponseDTO.PostDetailResponse.builder() + .OnGoing(voteOnGoing) + .isVoted(isVote) .postType(VOTE) .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) @@ -404,16 +419,18 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .OnGoing(voteOnGoing) - .isVoted(isVote) .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getGeneralPoll().getPollTitle()) .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) + .userVoteResult(userVoteResult) + .topVoteResult(topVoteResult) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) .point(post.getPoint()) .deadline(post.getGeneralPoll().getDeadline()) - .userVote(userChoiceList) - .percent(percent) - .voteResult(voteResult) .view(post.getView()) .like(likeCount) .comment(commentCount) @@ -421,73 +438,185 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .isComment(isComment) .myPost(myPost) .build(); - } - //나노초 단위로 마감 여부 확인 - LocalDateTime now = LocalDateTime.now(); - long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getCardPoll().getDeadline()); - Boolean voteOnGoing = nanosUntilDeadline > 0; - - List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - if(engage) { + } +//일반 투표 마감 후 //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() + Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() .filter(cardVote -> cardVote.getUser().getId().equals(userId)) .flatMap(cardVote -> cardVote.getSelect_list().stream()) .collect(Collectors.toSet()); - userChoiceList = post.getCardPoll().getCandidateList().stream() + userChoiceList = post.getGeneralPoll().getCandidateList().stream() .filter(candidate -> selectedOptionIds.contains(candidate.getId())) .map(PostConverter::toPollOptionResDTO) .collect(Collectors.toList()); - - // 총 투표수 계산 // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() + List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() .filter(vote -> vote.getUser().getId().equals(userId)) .flatMap(vote -> vote.getSelect_list().stream()) .collect(Collectors.toList()); - // 총 투표수 계산 - long totalVotes = post.getCardPoll().getCardVoteList().stream() + long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() .flatMap(vote -> vote.getSelect_list().stream()) .count(); - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() + Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() .flatMap(vote -> vote.getSelect_list().stream()) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + //1등 투표 계산 + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .max(); - // 사용자가 선택한 후보의 선택률 계산 - percent = userSelectedCandidateIds.stream() + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + topCandidateList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + + topCandidatePercent = mostVotedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); - // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) - voteResult = userSelectedCandidateIds.stream() + allCandidatePercent=post.getGeneralPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId=candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + userVoteResult = userSelectedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return String.format("%d/%d", selectionCount, totalVotes); }) .collect(Collectors.toList()); - isVote=true; - if(myPost){ - // 투표수가 가장 많은 후보의 선택률 계산 - OptionalDouble hightestCandidate = candidateSelectionCounts.values().stream() - .mapToDouble(aLong -> (double) aLong / totalVotes) - .max(); + topVoteResult = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + if (engage) { + return PostResponseDTO.PostDetailResponse.builder() + .OnGoing(false) + .isVoted(true) + .postType(VOTE) + .postVoteType(PostVoteType.GENERAL) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .createdAt(post.getCreatedAt()) + .title(post.getTitle()) + .content(post.getContent()) + .file(FileConverter.toFileDTO(post.getFileList())) + .pollTitle(post.getGeneralPoll().getPollTitle()) + .pollOption(pollOptionDTOList) + .userVoteResult(userVoteResult) + .topVoteResult(topVoteResult) + .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) + .userVoteResult(userVoteResult) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) + .point(post.getPoint()) + .deadline(post.getGeneralPoll().getDeadline()) + .view(post.getView()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .myPost(myPost) + .build(); - // 선택률이 가장 높은 후보의 ID들 찾기 - List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) - .map(Map.Entry::getKey) + } + return PostResponseDTO.PostDetailResponse.builder() + .OnGoing(false) + .isVoted(false) + .postType(VOTE) + .postVoteType(PostVoteType.GENERAL) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .title(post.getTitle()) + .content(post.getContent()) + .file(FileConverter.toFileDTO(post.getFileList())) + .pollTitle(post.getGeneralPoll().getPollTitle()) + .pollOption(pollOptionDTOList) + .userVoteResult(userVoteResult) + .topVoteResult(topVoteResult) + .topCandidate(topCandidateList) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) + .point(post.getPoint()) + .deadline(post.getGeneralPoll().getDeadline()) + .view(post.getView()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .myPost(myPost) + .build(); + + + + } +//카드 투표 상세 보기 + //나노초 단위로 마감 여부 확인 + LocalDateTime now = LocalDateTime.now(); + long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getCardPoll().getDeadline()); + Boolean voteOnGoing = nanosUntilDeadline > 0; + + //투표 후보 리스트 + List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); + if(post.getCardPoll().getDeadline().isAfter(LocalDateTime.now())){ + if(engage) { + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() + .filter(CardVote -> CardVote.getUser().getId().equals(userId)) + .flatMap(CardVote -> CardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) .collect(Collectors.toList()); + // 총 투표수 계산 + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); - percent = mostVotedCandidateIds.stream() + // 총 투표수 계산 + long totalVotes = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); @@ -495,65 +624,200 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .collect(Collectors.toList()); // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) - voteResult = mostVotedCandidateIds.stream() + userVoteResult = userSelectedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return String.format("%d/%d", selectionCount, totalVotes); }) .collect(Collectors.toList()); - } - if(myPost){ + isVote=true; // 투표수가 가장 많은 후보의 선택률 계산 OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() - .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .mapToDouble(aLong -> (double) aLong.getValue() / totalVotes) .max(); // 선택률이 가장 높은 후보의 ID들 찾기 List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) .map(Map.Entry::getKey) .collect(Collectors.toList()); - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 - userChoiceList = post.getCardPoll().getCandidateList().stream() + topCandidateList = post.getCardPoll().getCandidateList().stream() .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) .map(PostConverter::toPollOptionResDTO) .collect(Collectors.toList()); - percent = mostVotedCandidateIds.stream() + topCandidatePercent = mostVotedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); - // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) - voteResult = mostVotedCandidateIds.stream() + topVoteResult = mostVotedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return String.format("%d/%d", selectionCount, totalVotes); }) .collect(Collectors.toList()); } + return PostResponseDTO.PostDetailResponse.builder() + .OnGoing(voteOnGoing) + .isVoted(isVote) + .postType(VOTE) + .postVoteType(PostVoteType.CARD) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .createdAt(post.getCreatedAt()) + .title(post.getTitle()) + .content(post.getContent()) + .file(FileConverter.toFileDTO(post.getFileList())) + .pollTitle(post.getCardPoll().getPollTitle()) + .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) + .userVoteResult(userVoteResult) + .topVoteResult(topVoteResult) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) + .point(post.getPoint()) + .deadline(post.getCardPoll().getDeadline()) + .view(post.getView()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .myPost(myPost) + .build(); + } +//일반 투표 마감 후 + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); + // 총 투표수 계산 + long totalVotes = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + //1등 투표 계산 + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .max(); + + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + topCandidateList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + + topCandidatePercent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + allCandidatePercent=post.getCardPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId=candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + userVoteResult = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + topVoteResult = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + if (engage) { + return PostResponseDTO.PostDetailResponse.builder() + .OnGoing(false) + .isVoted(true) + .postType(VOTE) + .postVoteType(PostVoteType.CARD) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .createdAt(post.getCreatedAt()) + .title(post.getTitle()) + .content(post.getContent()) + .file(FileConverter.toFileDTO(post.getFileList())) + .pollTitle(post.getCardPoll().getPollTitle()) + .pollOption(pollOptionDTOList) + .userVoteResult(userVoteResult) + .topVoteResult(topVoteResult) + .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) + .userVoteResult(userVoteResult) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) + .point(post.getPoint()) + .deadline(post.getCardPoll().getDeadline()) + .view(post.getView()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .myPost(myPost) + .build(); + } return PostResponseDTO.PostDetailResponse.builder() + .OnGoing(false) + .isVoted(false) .postType(VOTE) .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) .userImg(userImg) - .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) - .OnGoing(voteOnGoing) - .isVoted(isVote) .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getCardPoll().getPollTitle()) .pollOption(pollOptionDTOList) + .userVoteResult(userVoteResult) + .topVoteResult(topVoteResult) + .topCandidate(topCandidateList) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) .point(post.getPoint()) .deadline(post.getCardPoll().getDeadline()) - .userVote(userChoiceList) - .percent(percent) - .voteResult(voteResult) .view(post.getView()) .like(likeCount) .comment(commentCount) @@ -795,6 +1059,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) .like(likeCount) .comment(commentCount) @@ -893,10 +1159,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .build(); } - System.out.println("여기서??????"); List pollOptionDTOList = post.getCardPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - System.out.println("!!!!!!!!!!!!!여기아님!!!!!!!!!!!!!!!!!"); if (!post.getCardPoll().getCardVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { engage = true; } @@ -1093,6 +1357,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) .like(likeCount) .comment(commentCount) diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index d1e4ea6..5c192f1 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -1,14 +1,12 @@ package friend.spring.web.dto; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; -import friend.spring.validation.annotation.TitleTextLimit; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.*; -import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.List; @@ -27,6 +25,9 @@ public static class AddPostResultDTO { @NoArgsConstructor @AllArgsConstructor public static class PostDetailResponse { + Boolean myPost; + Boolean OnGoing; + Boolean isVoted; //투표글에서만 사용, 후기글에서는 null PostType postType; PostVoteType postVoteType; String nickname; @@ -34,24 +35,26 @@ public static class PostDetailResponse { LocalDateTime createdAt; String title; String content; - Boolean OnGoing; - Boolean isVoted; //투표글에서만 사용, 후기글에서는 null List file; // 첨부파일 이미지 리스트 String pollTitle; // 투표글에서만 사용, 후기글에서는 null List pollOption; // 투표글에서만 사용, 후기글에서는 null - Integer gauge; // 게이지 투표글에서만 사용, 후기글에서는 null + List topCandidate; + List userVote;// 투표글에서 사용자가 투표완료시 투표한 후보 + List userVotePercent; // 투표글에서 사용자가 투표 완료시 투표한 후보 선택 퍼센트 + List topCandidatePercent; + List allCandidatePercent; + List userVoteResult; // 투표글에서 사용자가 투표 완료시 투표인원/총인원 + List topVoteResult; + Integer userGauge; // 게이지 투표글에서만 사용, 후기글에서는 null + Integer totalGauge; Integer point; // 투표글에서만 사용, 후기글에서는 null ParentPostDTO parentPost; // 후기글에서만 사용, 일반글에서는 null LocalDateTime deadline; // 투표글에서만 사용, 후기글에서는 null - List userVote; // 투표글에서 사용자가 투표완료시 투표한 후보 - List percent; // 투표글에서 사용자가 투표 완료시 투표한 후보 선택 퍼센트 - List voteResult; // 투표글에서 사용자가 투표 완료시 투표인원/총인원 Integer view; Integer like; Integer comment; Boolean isLike; Boolean isComment; - Boolean myPost; } From e8c3c7a7c2dec40bc6549a6e1162268acedbb25b Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sat, 17 Feb 2024 01:32:19 +0900 Subject: [PATCH 194/255] =?UTF-8?q?#138=20Feat=20:=20=EC=84=A4=EC=A0=95(?= =?UTF-8?q?=EA=B3=B5=EC=A7=80=EC=82=AC=ED=95=AD),=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20API=20=EA=B5=AC=ED=98=84,=20Notice=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 4 ++ .../spring/converter/MyPageConverter.java | 44 +++++++++++++++++-- .../java/friend/spring/domain/Notice.java | 27 ++++++++++++ src/main/java/friend/spring/domain/User.java | 4 ++ .../spring/repository/NoticeRepository.java | 11 +++++ .../friend/spring/service/MyPageService.java | 11 +++-- .../spring/service/MyPageServiceImpl.java | 24 ++++++++++ .../web/controller/MyPageRestController.java | 35 +++++++++++++-- .../spring/web/dto/MyPageResponseDTO.java | 32 ++++++++++++++ 9 files changed, 180 insertions(+), 12 deletions(-) create mode 100644 src/main/java/friend/spring/domain/Notice.java create mode 100644 src/main/java/friend/spring/repository/NoticeRepository.java diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 10454b8..55919db 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -29,6 +29,7 @@ public enum ErrorStatus implements BaseErrorCode { PASSWORD_INCORRECT(HttpStatus.NOT_FOUND, "USER4008", "비밀번호가 틀렸습니다."), PASSWORD_CHECK_INCORRECT(HttpStatus.NOT_FOUND, "USER4009", "확인 비밀번호가 일치하지 않습니다."), RTK_INCORREXT(HttpStatus.UNAUTHORIZED,"USER4100","RefreshToken값을 확인해주세요."), + NOT_ADMIN(HttpStatus.BAD_REQUEST, "USER4101", "관리자가 아닙니다."), // Auth 관련 AUTH_EXPIRED_TOKEN(HttpStatus.UNAUTHORIZED, "AUTH_4101", "토큰이 만료되었습니다."), @@ -70,6 +71,9 @@ public enum ErrorStatus implements BaseErrorCode { // 알림 관련 응답 ALARM_NOT_FOUND(HttpStatus.NOT_FOUND, "ALARM4001", "알림이 없습니다"), + + // 공지사항 관련 응답 + NOTICE_NOT_FOUND(HttpStatus.NOT_FOUND, "NOTICE4001", "공지사항이 없습니다.") ; private final HttpStatus httpStatus; diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index e081af8..35e4d56 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -1,9 +1,6 @@ package friend.spring.converter; -import friend.spring.domain.Category; -import friend.spring.domain.Inquiry; -import friend.spring.domain.Post; -import friend.spring.domain.User; +import friend.spring.domain.*; import friend.spring.domain.mapping.Post_scrap; import friend.spring.web.dto.MyPageRequestDTO; import friend.spring.web.dto.MyPageResponseDTO; @@ -136,4 +133,43 @@ public static MyPageResponseDTO.SavedPostCategoryDetailListRes toSavedPostCatego .postList(postCategoryDetailResList) .build(); } + + public static MyPageResponseDTO.NoticeRes toNoticeRes(Notice notice){ + long diffTime = notice.getCreatedAt().until(LocalDateTime.now(), ChronoUnit.SECONDS); // now보다 이후면 +, 전이면 - + diffTime = diffTime / SECOND; + diffTime = diffTime / MINUTE; + diffTime = diffTime / HOUR; + String adminImage = null; + if (notice.getUser().getFile() != null){ + adminImage = notice.getUser().getFile().getUrl(); + } + return MyPageResponseDTO.NoticeRes.builder() + .adminImage(adminImage) + .ago(diffTime) + .title(notice.getTitle()) + .content(notice.getContent()) + .build(); + } + + public static MyPageResponseDTO.NoticeListRes toNoticeListRes(Page noticeList){ + List noticeResList = noticeList.stream().map(MyPageConverter::toNoticeRes).collect(Collectors.toList()); + return MyPageResponseDTO.NoticeListRes.builder() + .noticeList(noticeResList) + .build(); + } + + public static MyPageResponseDTO.NoticeDetailRes toNoticeDetailRes(Notice notice){ + String adminImage = null; + if (notice.getUser().getFile() != null){ + adminImage = notice.getUser().getFile().getUrl(); + } + return MyPageResponseDTO.NoticeDetailRes.builder() + .adminImage(adminImage) + .adminName(notice.getUser().getNickname()) + .createdAt(notice.getCreatedAt()) + .content(notice.getContent()) + .view(notice.getView()) + .build(); + + } } diff --git a/src/main/java/friend/spring/domain/Notice.java b/src/main/java/friend/spring/domain/Notice.java new file mode 100644 index 0000000..d1b21c6 --- /dev/null +++ b/src/main/java/friend/spring/domain/Notice.java @@ -0,0 +1,27 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import lombok.*; + +import javax.persistence.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Notice extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String title; + + @Column(length = 1000) + private String content; + + private Integer view; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "admin_id") + private User user; +} diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 1eca1a7..5651133 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -123,6 +123,10 @@ public class User extends BaseEntity implements UserDetails { @OneToMany(mappedBy = "user") private List InquiryList = new ArrayList<>(); + @Builder.Default + @OneToMany(mappedBy = "user") + private List noticeList = new ArrayList<>(); + @OneToOne(mappedBy = "user") @JoinColumn(name = "file_id") private File file; diff --git a/src/main/java/friend/spring/repository/NoticeRepository.java b/src/main/java/friend/spring/repository/NoticeRepository.java new file mode 100644 index 0000000..54127cc --- /dev/null +++ b/src/main/java/friend/spring/repository/NoticeRepository.java @@ -0,0 +1,11 @@ +package friend.spring.repository; + +import friend.spring.domain.Notice; +import friend.spring.domain.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface NoticeRepository extends JpaRepository { + Page findAllByUser(User user, PageRequest pageRequest); +} diff --git a/src/main/java/friend/spring/service/MyPageService.java b/src/main/java/friend/spring/service/MyPageService.java index f550174..4be9480 100644 --- a/src/main/java/friend/spring/service/MyPageService.java +++ b/src/main/java/friend/spring/service/MyPageService.java @@ -1,9 +1,6 @@ package friend.spring.service; -import friend.spring.domain.Category; -import friend.spring.domain.Inquiry; -import friend.spring.domain.Post; -import friend.spring.domain.User; +import friend.spring.domain.*; import friend.spring.domain.mapping.Post_scrap; import friend.spring.web.dto.MyPageRequestDTO; import org.springframework.data.domain.Page; @@ -36,4 +33,10 @@ public interface MyPageService { Page getCategoryDetailList(Long userId, Long categoryId, Integer page); Category getCategory(Long categoryId); + + Page getNoticeList(Long userid, Integer page); + + User checkAdmin(Long adminId); + + Notice getNoticeDetail(Long noticeId); } diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index ad6aac4..1e2e820 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -5,6 +5,7 @@ import friend.spring.apiPayload.handler.PostHandler; import friend.spring.converter.MyPageConverter; import friend.spring.domain.*; +import friend.spring.domain.enums.RoleType; import friend.spring.domain.enums.S3ImageType; import friend.spring.domain.mapping.Post_scrap; import friend.spring.repository.*; @@ -44,6 +45,7 @@ public class MyPageServiceImpl implements MyPageService{ private final JwtTokenProvider jwtTokenProvider; private final S3Service s3Service; private final InquiryRepository inquiryRepository; + private final NoticeRepository noticeRepository; BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @@ -183,5 +185,27 @@ public Category getCategory(Long categoryId) { return category; } + @Override + public Page getNoticeList(Long userId, Integer page) { + User admin = checkAdmin(userId); + Page noticeList = noticeRepository.findAllByUser(admin, PageRequest.of(page, 10)); + return noticeList; + } + + @Override + public User checkAdmin(Long adminId) { + User user = userRepository.findById(adminId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + if (user.getRole() == RoleType.USER){ + throw new GeneralException(ErrorStatus.NOT_ADMIN); + } + return user; + } + + @Override + public Notice getNoticeDetail(Long noticeId) { + Notice notice = noticeRepository.findById(noticeId).orElseThrow(() -> new GeneralException(ErrorStatus.NOTICE_NOT_FOUND)); + return notice; + } + } diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index 89a3f4c..3ad75bf 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -3,10 +3,7 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.CommentConverter; import friend.spring.converter.MyPageConverter; -import friend.spring.domain.Category; -import friend.spring.domain.Inquiry; -import friend.spring.domain.Post; -import friend.spring.domain.User; +import friend.spring.domain.*; import friend.spring.domain.mapping.Comment_choice; import friend.spring.service.*; import friend.spring.web.dto.CommentResponseDTO; @@ -259,4 +256,34 @@ public ApiResponse GetUserCate Category category = myPageService.getCategory(categoryId); return ApiResponse.onSuccess(MyPageConverter.toSavedPostCategoryDetailListRes(categoryDetailList, category)); } + + @GetMapping(value = "/setting/notice") + @Operation(summary = "공지사항 리스트 조회 API", description = "전체 공지사항의 리스트를 조회하는 API입니다. ex) /user/my-page/setting/notice") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "NOTICE4001",description = "NOT_FOUND, 공지사항이 없습니다."), + }) + @Parameters({ + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), + }) + public ApiResponse getNoticeList( + @RequestParam(name = "page", defaultValue = "0") Integer page){ + Page noticeList = myPageService.getNoticeList(Long.parseLong("30"), page); + return ApiResponse.onSuccess(MyPageConverter.toNoticeListRes(noticeList)); + } + + @GetMapping(value = "/setting/notice/{notice-id}") + @Operation(summary = "공지사항 상세 조회 API", description = "전체 공지사항 상세내용을 조회하는 API입니다. ex) /user/my-page/setting/notice/{notice-id}") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "NOTICE4001",description = "NOT_FOUND, 공지사항이 없습니다."), + }) + @Parameters({ + }) + public ApiResponse getNoticeDetail( + @PathVariable("notice-id") Long noticeId + ){ + Notice noticeDetail = myPageService.getNoticeDetail(noticeId); + return ApiResponse.onSuccess(MyPageConverter.toNoticeDetailRes(noticeDetail)); + } } diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index 609ec99..d5fd5d1 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -7,6 +7,7 @@ import javax.validation.constraints.Email; import javax.validation.constraints.NotEmpty; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import java.util.Set; @@ -118,4 +119,35 @@ public static class SavedPostCategoryDetailListRes{ String name; List postList; } + + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class NoticeListRes{ + List noticeList; + } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class NoticeRes{ + String adminImage; + Long ago; + String title; + String content; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class NoticeDetailRes{ + String adminImage; + String adminName; + LocalDateTime createdAt; + String content; + Integer view; + } } From 4895cb3cdd688f46fa8dd87b8c3ce05ff972931f Mon Sep 17 00:00:00 2001 From: hjh Date: Sat, 17 Feb 2024 02:33:39 +0900 Subject: [PATCH 195/255] =?UTF-8?q?#137=20=ED=88=AC=ED=91=9C=20=ED=9A=9F?= =?UTF-8?q?=EC=88=98=20=EC=A0=9C=ED=95=9C(=EC=B5=9C=EB=8C=801=EB=B2=88)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/apiPayload/code/status/ErrorStatus.java | 2 ++ .../friend/spring/service/VoteServiceImpl.java | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 10454b8..d90d633 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -57,6 +57,8 @@ public enum ErrorStatus implements BaseErrorCode { POST_LIKE_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4014", "글에 대한 좋아요 데이터가 이미 존재합니다."), POST_SCRAP_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4015", "글에 대한 스크랩 데이터가 이미 존재합니다."), DEADLINE_OVER(HttpStatus.BAD_REQUEST,"POST4016","투표 마감 시간이 지났습니다"), + ALREADY_VOTE(HttpStatus.BAD_REQUEST,"POST4017","이미 투표 하셨습니다."), +// USER_VOTE(HttpStatus.BAD_REQUEST,"POST4017","작성자는 투표가 불가능 합니다 하셨습니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index cc7543d..4284adf 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -14,6 +14,7 @@ import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; @Service @@ -37,6 +38,10 @@ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request Post post=postRepository.findById(PostId) .orElseThrow(()-> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + if(post.getGeneralPoll().getGeneralVoteList().stream().anyMatch(generalVote -> generalVote.getUser().getId().equals(userId))){ + throw new GeneralException(ErrorStatus.ALREADY_VOTE); + } + General_poll generalPoll=post.getGeneralPoll(); newGeneralVote.setGeneralPoll(generalPoll); @@ -83,9 +88,14 @@ public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long Post post=postRepository.findById(PostId) .orElseThrow(()-> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + if(post.getGaugePoll().getGaugeVoteList().stream().anyMatch(gaugeVote -> gaugeVote.getUser().getId().equals(userId))){ + throw new GeneralException(ErrorStatus.ALREADY_VOTE); + } Gauge_poll gaugePoll=post.getGaugePoll(); newGaugeVote.setGaugePoll(gaugePoll); + + //나노초 단위로 마감 여부 확인 LocalDateTime now = LocalDateTime.now(); long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGaugePoll().getDeadline()); @@ -123,7 +133,9 @@ public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request,Long Pos Post post=postRepository.findById(PostId) .orElseThrow(()-> new GeneralException(ErrorStatus.POST_NOT_FOUND)); - + if(post.getCardPoll().getCardVoteList().stream().anyMatch(cardVote -> cardVote.getUser().getId().equals(userId))){ + throw new GeneralException(ErrorStatus.ALREADY_VOTE); + } Card_poll cardPoll=post.getCardPoll(); newCardVote.setCardPoll(cardPoll); From dae3a887d268e72b916ac52487c404acc9d064fa Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 17 Feb 2024 05:10:17 +0900 Subject: [PATCH 196/255] =?UTF-8?q?#113=20Refactor:=20=EC=95=8C=EB=A6=BC?= =?UTF-8?q?=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=A1=B0=ED=9A=8C=EC=97=90?= =?UTF-8?q?=EC=84=9C=20read=EB=8F=84=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/AlarmConverter.java | 18 ++++++++++++------ .../spring/web/dto/AlarmResponseDTO.java | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/friend/spring/converter/AlarmConverter.java b/src/main/java/friend/spring/converter/AlarmConverter.java index 43f2944..8a23f9c 100644 --- a/src/main/java/friend/spring/converter/AlarmConverter.java +++ b/src/main/java/friend/spring/converter/AlarmConverter.java @@ -15,24 +15,30 @@ public class AlarmConverter { //알림 public static AlarmResponseDTO.AlarmResDTO toAlarmResDTO(Alarm alarm){ - String userPhoto = null; - if (alarm.getUser().getFile() != null) { - userPhoto = alarm.getUser().getFile().getUrl(); - } - Long commentId = null; + String commentContent = null; + String userNickname = null; + String userPhoto = null; if (alarm.getComment() != null) { commentId = alarm.getComment().getId(); + commentContent = alarm.getComment().getContent(); + userNickname = alarm.getComment().getUser().getNickname(); + if (alarm.getComment().getUser().getFile() != null) { + userPhoto = alarm.getComment().getUser().getFile().getUrl(); + } } return AlarmResponseDTO.AlarmResDTO.builder() - .userNickname(alarm.getUser().getNickname()) + .alarmId(alarm.getId()) + .userNickname(userNickname) .userPhoto(userPhoto) .alarmType(alarm.getType().toString()) .alarmContent(alarm.getContent()) .postId(alarm.getPost().getId()) .commentId(commentId) + .commentContent(commentContent) .createdAt(alarm.getCreatedAt()) + .read(alarm.getRead()) .build(); } diff --git a/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java b/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java index 899c0f8..351e6d2 100644 --- a/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java @@ -1,6 +1,5 @@ package friend.spring.web.dto; -import friend.spring.domain.enums.AlarmType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -31,6 +30,7 @@ public static class AlarmResDTO{ String commentContent; Long postId; Long commentId; + Boolean read; LocalDateTime createdAt; } From aee200cc5cb34cd58c9c9eee6a128cc8f9ad6857 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 17 Feb 2024 16:12:02 +0900 Subject: [PATCH 197/255] =?UTF-8?q?#147=20Refactor:=20=EA=B8=80=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=EB=B3=B4=EA=B8=B0=20=EC=8B=9C=20=ED=9B=84?= =?UTF-8?q?=EB=B3=B4=20=EC=95=84=EC=9D=B4=EB=94=94=EB=8F=84=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/PostConverter.java | 1 + src/main/java/friend/spring/web/dto/PollOptionDTO.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index bf2ba95..8e2c4c1 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -41,6 +41,7 @@ public static PollOptionDTO.PollOptionRes toPollOptionResDTO(Candidate candidate optionImgUrl = candidate.getFile().getUrl(); } return PollOptionDTO.PollOptionRes.builder() + .optionId(candidate.getId()) .optionString(candidate.getName()) .optionImgUrl(optionImgUrl).build(); } diff --git a/src/main/java/friend/spring/web/dto/PollOptionDTO.java b/src/main/java/friend/spring/web/dto/PollOptionDTO.java index 379e1fc..8260c80 100644 --- a/src/main/java/friend/spring/web/dto/PollOptionDTO.java +++ b/src/main/java/friend/spring/web/dto/PollOptionDTO.java @@ -23,6 +23,7 @@ public static class PollOptionReq { @NoArgsConstructor @AllArgsConstructor public static class PollOptionRes { + private Long optionId; private String optionString; private String optionImgUrl; } From b55149a039059a25fd5a782c3559dd9f71e4fd28 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sat, 17 Feb 2024 17:16:25 +0900 Subject: [PATCH 198/255] =?UTF-8?q?#143=20Feat=20:=20=EC=84=A4=EC=A0=95(?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=EC=95=BD=EA=B4=80),=20=EC=84=A4=EC=A0=95(?= =?UTF-8?q?=EA=B0=9C=EC=9D=B8=EC=A0=95=EB=B3=B4=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=EB=B0=A9=EC=B9=A8)=20API=20=EA=B5=AC=ED=98=84,=20Term=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/MyPageConverter.java | 11 +++++++ src/main/java/friend/spring/domain/Term.java | 27 +++++++++++++++++ src/main/java/friend/spring/domain/User.java | 4 +++ .../spring/repository/TermRepository.java | 7 +++++ .../friend/spring/service/MyPageService.java | 4 +++ .../spring/service/MyPageServiceImpl.java | 17 +++++++++++ .../web/controller/MyPageRestController.java | 29 ++++++++++++++++++- .../spring/web/dto/MyPageResponseDTO.java | 16 ++++++++++ 8 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/main/java/friend/spring/domain/Term.java create mode 100644 src/main/java/friend/spring/repository/TermRepository.java diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index 35e4d56..19df72c 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -170,6 +170,17 @@ public static MyPageResponseDTO.NoticeDetailRes toNoticeDetailRes(Notice notice) .content(notice.getContent()) .view(notice.getView()) .build(); + } + public static MyPageResponseDTO.TermRes toTermRes(Term term){ + return MyPageResponseDTO.TermRes.builder() + .content(term.getTerm()) + .build(); + } + + public static MyPageResponseDTO.PrivacyRes toPrivacyRes(Term term){ + return MyPageResponseDTO.PrivacyRes.builder() + .content(term.getPrivacy()) + .build(); } } diff --git a/src/main/java/friend/spring/domain/Term.java b/src/main/java/friend/spring/domain/Term.java new file mode 100644 index 0000000..8b29f58 --- /dev/null +++ b/src/main/java/friend/spring/domain/Term.java @@ -0,0 +1,27 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import lombok.*; + +import javax.persistence.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Term extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(length = 50000) + private String term; + + @Column(length = 50000) + private String privacy; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "admin_id") + private User user; +} diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 5651133..73a0531 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -127,6 +127,10 @@ public class User extends BaseEntity implements UserDetails { @OneToMany(mappedBy = "user") private List noticeList = new ArrayList<>(); + @Builder.Default + @OneToMany(mappedBy = "user") + private List termList = new ArrayList<>(); + @OneToOne(mappedBy = "user") @JoinColumn(name = "file_id") private File file; diff --git a/src/main/java/friend/spring/repository/TermRepository.java b/src/main/java/friend/spring/repository/TermRepository.java new file mode 100644 index 0000000..a48426c --- /dev/null +++ b/src/main/java/friend/spring/repository/TermRepository.java @@ -0,0 +1,7 @@ +package friend.spring.repository; + +import friend.spring.domain.Term; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TermRepository extends JpaRepository { +} diff --git a/src/main/java/friend/spring/service/MyPageService.java b/src/main/java/friend/spring/service/MyPageService.java index 4be9480..c3c95ef 100644 --- a/src/main/java/friend/spring/service/MyPageService.java +++ b/src/main/java/friend/spring/service/MyPageService.java @@ -39,4 +39,8 @@ public interface MyPageService { User checkAdmin(Long adminId); Notice getNoticeDetail(Long noticeId); + + Term getTerm(Long userId); + + Term getPrivacy(Long userId); } diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index 1e2e820..ef12abe 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -46,6 +46,7 @@ public class MyPageServiceImpl implements MyPageService{ private final S3Service s3Service; private final InquiryRepository inquiryRepository; private final NoticeRepository noticeRepository; + private final TermRepository termRepository; BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @@ -207,5 +208,21 @@ public Notice getNoticeDetail(Long noticeId) { return notice; } + @Override + public Term getTerm(Long userId) { + User admin = checkAdmin(userId); + Long termId = 1L; + Term term = termRepository.findById(termId).get(); + return term; + } + + @Override + public Term getPrivacy(Long userId) { + User admin = checkAdmin(userId); + Long privacyId = 1L; + Term privacy = termRepository.findById(privacyId).get(); + return privacy; + } + } diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index 3ad75bf..c5dd862 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -268,7 +268,7 @@ public ApiResponse GetUserCate }) public ApiResponse getNoticeList( @RequestParam(name = "page", defaultValue = "0") Integer page){ - Page noticeList = myPageService.getNoticeList(Long.parseLong("30"), page); + Page noticeList = myPageService.getNoticeList(30L, page); return ApiResponse.onSuccess(MyPageConverter.toNoticeListRes(noticeList)); } @@ -279,6 +279,7 @@ public ApiResponse getNoticeList( @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "NOTICE4001",description = "NOT_FOUND, 공지사항이 없습니다."), }) @Parameters({ + @Parameter(name = "notice-id", description = "path variable - 공지사항 아이디"), }) public ApiResponse getNoticeDetail( @PathVariable("notice-id") Long noticeId @@ -286,4 +287,30 @@ public ApiResponse getNoticeDetail( Notice noticeDetail = myPageService.getNoticeDetail(noticeId); return ApiResponse.onSuccess(MyPageConverter.toNoticeDetailRes(noticeDetail)); } + + @GetMapping(value = "/setting/term") + @Operation(summary = "이용약관 조회 API", description = "이용약관을 조회하는 API입니다. ex) /user/my-page/setting/term") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + }) + @Parameters({ + }) + public ApiResponse getTerm( + ){ + Term term = myPageService.getTerm(30L); + return ApiResponse.onSuccess(MyPageConverter.toTermRes(term)); + } + + @GetMapping(value = "/setting/privacy") + @Operation(summary = "개인정보 처리방침 조회 API", description = "개인정보 처리방침을 조회하는 API입니다. ex) /user/my-page/setting/privacy") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), + }) + @Parameters({ + }) + public ApiResponse getPrivacy( + ){ + Term term = myPageService.getPrivacy(30L); + return ApiResponse.onSuccess(MyPageConverter.toPrivacyRes(term)); + } } diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index d5fd5d1..1b949bc 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -150,4 +150,20 @@ public static class NoticeDetailRes{ String content; Integer view; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class TermRes{ + String content; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class PrivacyRes{ + String content; + } } From bf87be404e45b1985fd32b66977bca084a041d02 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sat, 17 Feb 2024 17:40:28 +0900 Subject: [PATCH 199/255] =?UTF-8?q?#150=20Refactor=20:=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=EB=90=9C=20=EA=B8=80,=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=8B=9C=EA=B0=84=EB=B0=98=ED=99=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/MyPageConverter.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index 19df72c..2a592ef 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -32,10 +32,8 @@ public static MyPageResponseDTO.SavedCategoryResDTO toSavedCategoryResDTO(List Date: Sat, 17 Feb 2024 18:12:22 +0900 Subject: [PATCH 200/255] =?UTF-8?q?#147=20Refactor:=20=EB=8C=93=EA=B8=80?= =?UTF-8?q?=20=EC=83=81=EC=84=B8=EB=B3=B4=EA=B8=B0=20=EB=8C=80=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EA=B4=80=EB=A0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/service/CommentServiceImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index d8ccf0d..96ebbec 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -196,9 +196,9 @@ public List getComments(Long postId, HttpServl List subComments = new ArrayList<>(); if (comment.getSubCommentList() != null) { for (Comment c : comment.getSubCommentList()) { - Boolean isPushedLike_sub = checkIsPushedLike(comment, loginUserId); - Boolean isOwnerOfPost_sub = checkIsOwnerOfPost(comment, loginUserId); - CommentResponseDTO.commentGetRes subCommentGetRes = CommentConverter.toCommentGetRes(comment, loginUserId, isPushedLike_sub, isOwnerOfPost_sub, new ArrayList<>()); + Boolean isPushedLike_sub = checkIsPushedLike(c, loginUserId); + Boolean isOwnerOfPost_sub = checkIsOwnerOfPost(c, loginUserId); + CommentResponseDTO.commentGetRes subCommentGetRes = CommentConverter.toCommentGetRes(c, loginUserId, isPushedLike_sub, isOwnerOfPost_sub, new ArrayList<>()); subComments.add(subCommentGetRes); } } From 9789dcb1b577efc3e4967cbf015412080f0f32fc Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 17 Feb 2024 18:54:51 +0900 Subject: [PATCH 201/255] =?UTF-8?q?#146=20Refactor:=20=ED=99=88=20-=20?= =?UTF-8?q?=EB=8B=B5=EB=B3=80=EC=9D=84=20=EA=B8=B0=EB=8B=A4=EB=A6=AC?= =?UTF-8?q?=EB=8A=94=20=EA=B3=A0=EB=AF=BC=EB=93=A4=20/=20=ED=99=88=20-=20?= =?UTF-8?q?=EC=A7=80=EA=B8=88=20=EA=B0=80=EC=9E=A5=20=ED=95=AB=ED=95=9C=20?= =?UTF-8?q?=EA=B3=A0=EB=AF=BC=ED=88=AC=ED=91=9C=20=EB=A6=AC=ED=84=B4=20?= =?UTF-8?q?=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/CandidateConverter.java | 15 --- .../spring/converter/PostConverter.java | 23 ---- .../spring/repository/PostRepository.java | 7 +- .../friend/spring/service/PostService.java | 6 +- .../spring/service/PostServiceImpl.java | 114 ++++-------------- .../web/controller/PostRestController.java | 22 ++-- .../spring/web/dto/CandidateResponseDTO.java | 1 + .../spring/web/dto/PostResponseDTO.java | 21 ---- 8 files changed, 43 insertions(+), 166 deletions(-) diff --git a/src/main/java/friend/spring/converter/CandidateConverter.java b/src/main/java/friend/spring/converter/CandidateConverter.java index 62e4a9d..f11e739 100644 --- a/src/main/java/friend/spring/converter/CandidateConverter.java +++ b/src/main/java/friend/spring/converter/CandidateConverter.java @@ -4,21 +4,6 @@ import friend.spring.web.dto.CandidateResponseDTO; public class CandidateConverter { - - public static CandidateResponseDTO.CandidateSummaryRes toCandidateSummaryRes(Candidate candidate, Double percent) { - String candidate_image = null; - if (candidate.getFile() != null) { - candidate_image = candidate.getFile().getUrl(); - } - - return CandidateResponseDTO.CandidateSummaryRes.builder() - .candidate_id(candidate.getId()) - .candidate_name(candidate.getName()) - .candidate_image(candidate_image) - .ratio(percent) - .build(); - } - public static CandidateResponseDTO.AddCandidateResultDTO toAddCandidateResultDTO(Candidate candidate) { return CandidateResponseDTO.AddCandidateResultDTO.builder() .candidateId(candidate.getId()) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 8e2c4c1..0fd3707 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -1459,29 +1459,6 @@ public static PostResponseDTO.PostLikeRes toPostLikeRes(Post_like post_like) { .build(); } - public static PostResponseDTO.PostSummaryListRes toPostSummaryRes(Post post, Integer like_cnt, Integer comment_cnt, String postVoteType, - List candidateSummaryResList, - Integer gauge, - Long general_poll_id, Long gauge_poll_id, Long card_poll_id - ) { - return PostResponseDTO.PostSummaryListRes.builder() - .title(post.getTitle()) - .content(post.getContent()) - .post_id(post.getId()) - .file(FileConverter.toFileDTO(post.getFileList())) - .like(like_cnt) - .comment_cnt(comment_cnt) - .created_at(post.getCreatedAt()) - .user(UserConverter.toUserSummaryInfo(post.getUser())) - .postVoteType(postVoteType) - .general_poll_id(general_poll_id) - .gauge_poll_id(gauge_poll_id) - .card_poll_id(card_poll_id) - .gauge(gauge) - .candidateList(candidateSummaryResList) - .build(); - } - public static Post_scrap toPostScrap(Post post, User user) { return Post_scrap.builder() .post(post) diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index 3ac3789..bf455eb 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -7,23 +7,20 @@ import io.lettuce.core.dynamic.annotation.Param; import org.springframework.data.domain.Page; import friend.spring.domain.User; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; -import java.util.List; +import java.time.LocalDateTime; public interface PostRepository extends JpaRepository { Page findByPostTypeAndState(PostType postType, PostState state, Pageable pageable); Page findByPostTypeAndStateAndCategory(PostType postType, PostState state,Category category,Pageable pageable); Page findByUserIdAndPostTypeAndState(Long userId, PostType postType, PostState state, Pageable pageable); Page findAllByUser(User user, PageRequest pageRequest); - @Query(value = "SELECT * FROM post WHERE post.created_at >= DATE_ADD(now(), INTERVAL -7 DAY) ORDER BY post.point DESC", nativeQuery = true) - Page findBestPosts(Pageable pageable); - Page findAllByOrderByCreatedAtDesc(Pageable pageable); + Page findByPostTypeAndStateAndCreatedAtAfter(PostType postType, PostState state, LocalDateTime sevenDaysAgo, Pageable pageable); @Query(value = "SELECT p FROM Post p JOIN p.postScrapList s JOIN p.category c WHERE s.user.id = :userId and c.id = :categoryId") Page findCategoryDetail(Long userId, Long categoryId, PageRequest pageRequest); diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index 1ba8ac9..fd47bc5 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -44,11 +44,9 @@ public interface PostService { void checkPostScrap(Boolean flag); - Page getBestPosts(Integer page, Integer size); + PostResponseDTO.PollPostGetListDTO getBestPosts(Integer page, Integer size, HttpServletRequest request); - Page getRecentPosts(Integer page, Integer size); - - List getPostRes(Page postPage); + PostResponseDTO.PollPostGetListDTO getRecentPosts(Integer page, Integer size, HttpServletRequest request); Post_scrap createScrapPost(Long postId, HttpServletRequest request); diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 44401e3..a09de34 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -4,9 +4,9 @@ import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.apiPayload.handler.PostHandler; import friend.spring.apiPayload.handler.UserHandler; -import friend.spring.converter.CandidateConverter; import friend.spring.converter.PostConverter; import friend.spring.domain.*; +import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.S3ImageType; import friend.spring.domain.mapping.Post_like; @@ -15,23 +15,16 @@ import friend.spring.security.JwtTokenProvider; import friend.spring.web.dto.*; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; -import java.util.Objects; import javax.servlet.http.HttpServletRequest; import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; import static friend.spring.apiPayload.code.status.ErrorStatus.*; import static friend.spring.domain.enums.PostType.*; @@ -402,91 +395,32 @@ public void dislikePost(Long postId, HttpServletRequest request) { } @Override - public Page getBestPosts(Integer page, Integer size) { - Pageable pageable = PageRequest.of(page, size); - Page bestPostPage = postRepository.findBestPosts(pageable); - List postResList = getPostRes(bestPostPage); - return new PageImpl<>(postResList, pageable, bestPostPage.getTotalElements()); - } + public PostResponseDTO.PollPostGetListDTO getBestPosts(Integer page, Integer size, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } - @Override - public Page getRecentPosts(Integer page, Integer size) { - Pageable pageable = PageRequest.of(page, size); - Page recentPostPage = postRepository.findAllByOrderByCreatedAtDesc(pageable); - List postResList = getPostRes(recentPostPage); - return new PageImpl<>(postResList, pageable, recentPostPage.getTotalElements()); + LocalDateTime minusDays = LocalDateTime.now().minusDays(7); // 7일 이내 + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "point")); + Page bestPostPage = postRepository.findByPostTypeAndStateAndCreatedAtAfter(PostType.VOTE, PostState.POSTING, minusDays, pageable); + + return PostConverter.pollPostGetListDTO(bestPostPage,userId); } @Override - public List getPostRes(Page postPage) { - return postPage - .map(post -> { - Integer like_cnt = postLikeRepository.countByPostId(post.getId()); - Integer comment_cnt = commentRepository.countByPostId(post.getId()); - String postVoteType = null; - Long general_poll_id = null; - Long gauge_poll_id = null; - Long card_poll_id = null; - Integer gauge = null; - List candidateList = null; - List candidateSummaryResList = null; - - if (post.getPostType().equals(REVIEW)) return null; // 고민 후기 글인 경우 패스 - - if (post.getVoteType().equals(GENERAL)) { // 일반 투표인 경우 - postVoteType = "GENERAL"; - general_poll_id = post.getGeneralPoll().getId(); - candidateList = candidateRepository.findAllByGeneralPollId(general_poll_id); - candidateSummaryResList = new ArrayList<>(); - - // 총 투표수 계산 - Double totalVotes = (double) post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); - - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - - for (Candidate candidate : candidateList) { - long selectionCount = candidateSelectionCounts.getOrDefault(candidate.getId(), 0L); - Double percent = (double) selectionCount / totalVotes * 100; - candidateSummaryResList.add(CandidateConverter.toCandidateSummaryRes(candidate, percent)); - } - } else if (post.getVoteType().equals(GAUGE)) { - postVoteType = "GAUGE"; - gauge_poll_id = post.getGaugePoll().getId(); - gauge = post.getGaugePoll().getGauge(); - } else { - postVoteType = "CARD"; - card_poll_id = post.getCardPoll().getId(); - candidateList = candidateRepository.findAllByCardPollId(card_poll_id); - candidateSummaryResList = new ArrayList<>(); - - // 총 투표수 계산 - Double totalVotes = (double) post.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); - - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - - for (Candidate candidate : candidateList) { - long selectionCount = candidateSelectionCounts.getOrDefault(candidate.getId(), 0L); - Double percent = (double) selectionCount / totalVotes * 100; - candidateSummaryResList.add(CandidateConverter.toCandidateSummaryRes(candidate, percent)); - } - } - - PostResponseDTO.PostSummaryListRes postGetRes = PostConverter.toPostSummaryRes(post, like_cnt, comment_cnt, postVoteType, candidateSummaryResList, gauge, general_poll_id, gauge_poll_id, card_poll_id); - return postGetRes; - }) - .filter(Objects::nonNull) // null인 요소는 필터링 - .get() - .collect(Collectors.toList()); + public PostResponseDTO.PollPostGetListDTO getRecentPosts(Integer page, Integer size, HttpServletRequest request) { + Long userId = jwtTokenProvider.getCurrentUser(request); + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); + Page recentPostPage = postRepository.findByPostTypeAndState(PostType.VOTE, PostState.POSTING, pageable); + + return PostConverter.pollPostGetListDTO(recentPostPage,userId); } @Override diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index abfcc51..2b2e998 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -230,13 +230,16 @@ public ApiResponse dislikePost( }) @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), - @Parameter(name = "size", description = "query string(RequestParam) - 한 번에 글 몇 개씩 불러올지 개수를 세는 변수 (1 이상 자연수로 설정)") + @Parameter(name = "size", description = "query string(RequestParam) - 한 번에 글 몇 개씩 불러올지 개수를 세는 변수 (1 이상 자연수로 설정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) - public ApiResponse> getBestPosts( + public ApiResponse getBestPosts( @RequestParam(name = "page") Integer page, - @RequestParam(name = "size") Integer size + @RequestParam(name = "size") Integer size, + @RequestHeader("atk") String atk, + HttpServletRequest request ) { - return ApiResponse.onSuccess(postService.getBestPosts(page, size)); + return ApiResponse.onSuccess(postService.getBestPosts(page, size, request)); } // 홈 - 답변을 기다리는 고민들 @@ -247,13 +250,16 @@ public ApiResponse> getBestPosts( }) @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), - @Parameter(name = "size", description = "query string(RequestParam) - 한 번에 글 몇 개씩 불러올지 개수를 세는 변수 (1 이상 자연수로 설정)") + @Parameter(name = "size", description = "query string(RequestParam) - 한 번에 글 몇 개씩 불러올지 개수를 세는 변수 (1 이상 자연수로 설정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) - public ApiResponse> getRecentPosts( + public ApiResponse getRecentPosts( @RequestParam(name = "page") Integer page, - @RequestParam(name = "size") Integer size + @RequestParam(name = "size") Integer size, + @RequestHeader("atk") String atk, + HttpServletRequest request ) { - return ApiResponse.onSuccess(postService.getRecentPosts(page, size)); + return ApiResponse.onSuccess(postService.getRecentPosts(page, size, request)); } // 글 스크랩 추가 diff --git a/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java b/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java index 999f16e..e7d730b 100644 --- a/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CandidateResponseDTO.java @@ -14,6 +14,7 @@ public static class CandidateSummaryRes { String candidate_name; // 후보 이름 String candidate_image; // 후보 이미지 Double ratio; // 비율 + Boolean mySelect; // 사용자가 투표했는지 여부 } @Builder diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 5c192f1..1f08e3c 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -141,27 +141,6 @@ public static class PostLikeRes { Long post_like_id; } - @Builder - @Getter - @NoArgsConstructor - @AllArgsConstructor - public static class PostSummaryListRes { - String title; - String content; - Long post_id; - List file; - Integer like; - Integer comment_cnt; - LocalDateTime created_at; - UserResponseDTO.UserSummaryInfo user; - String postVoteType; - Long general_poll_id; - Long gauge_poll_id; - Long card_poll_id; - Integer gauge; - List candidateList; - } - @Builder @Getter @NoArgsConstructor From 319ab1eb1ed28c5bb779c0771679c094e1585c28 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 17 Feb 2024 23:20:48 +0900 Subject: [PATCH 202/255] =?UTF-8?q?#155=20Refactor:=20=EB=8C=93=EA=B8=80?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20=EC=B1=84=ED=83=9D=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=EB=8F=84=20=EB=A6=AC=ED=84=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/CommentConverter.java | 3 ++- .../repository/CommentChoiceRepository.java | 2 ++ .../spring/service/CommentServiceImpl.java | 22 +++++++++++++++++-- .../spring/web/dto/CommentResponseDTO.java | 1 + 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index 3373d77..20fac64 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -43,7 +43,7 @@ public static CommentResponseDTO.commentLikeRes toCommentLikeRes(Comment_like co .build(); } - public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment, Long loginUserId, Boolean isPushedLike, Boolean isOwnerOfPost, List subComments) { + public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment, Long loginUserId, Boolean isPushedLike, Boolean isOwnerOfPost, Boolean isSelected, List subComments) { Long parentCommentId = null; if (comment.getParentComment() != null) { parentCommentId = comment.getParentComment().getId(); @@ -86,6 +86,7 @@ public static CommentResponseDTO.commentGetRes toCommentGetRes(Comment comment, .isMyComment(isMyComment) .isPushedLike(isPushedLike) .isOwnerOfPost(isOwnerOfPost) + .isSelected(isSelected) .build(); } diff --git a/src/main/java/friend/spring/repository/CommentChoiceRepository.java b/src/main/java/friend/spring/repository/CommentChoiceRepository.java index e246cc3..5b2fdc8 100644 --- a/src/main/java/friend/spring/repository/CommentChoiceRepository.java +++ b/src/main/java/friend/spring/repository/CommentChoiceRepository.java @@ -7,4 +7,6 @@ public interface CommentChoiceRepository extends JpaRepository { Optional findByPostId(Long postId); + + Optional findByCommentIdAndPostId(Long commentId, Long postId); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 96ebbec..fcfb1e9 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -198,15 +198,17 @@ public List getComments(Long postId, HttpServl for (Comment c : comment.getSubCommentList()) { Boolean isPushedLike_sub = checkIsPushedLike(c, loginUserId); Boolean isOwnerOfPost_sub = checkIsOwnerOfPost(c, loginUserId); - CommentResponseDTO.commentGetRes subCommentGetRes = CommentConverter.toCommentGetRes(c, loginUserId, isPushedLike_sub, isOwnerOfPost_sub, new ArrayList<>()); + Boolean isSelected = checkIsSelected(c); + CommentResponseDTO.commentGetRes subCommentGetRes = CommentConverter.toCommentGetRes(c, loginUserId, isPushedLike_sub, isOwnerOfPost_sub, isSelected, new ArrayList<>()); subComments.add(subCommentGetRes); } } Boolean isPushedLike = checkIsPushedLike(comment, loginUserId); Boolean isOwnerOfPost = checkIsOwnerOfPost(comment, loginUserId); + Boolean isSelected = checkIsSelected(comment); - CommentResponseDTO.commentGetRes commentGetRes = CommentConverter.toCommentGetRes(comment, loginUserId, isPushedLike, isOwnerOfPost, subComments); + CommentResponseDTO.commentGetRes commentGetRes = CommentConverter.toCommentGetRes(comment, loginUserId, isPushedLike, isOwnerOfPost, isSelected, subComments); commentGetResList.add(commentGetRes); } @@ -236,6 +238,22 @@ public Boolean checkIsOwnerOfPost(Comment comment, Long loginUserId) { return isOwnerOfPost; } + public Boolean checkIsSelected(Comment comment) { + Optional optionalComment_choice = commentChoiceRepository.findByCommentIdAndPostId(comment.getId(), comment.getPost().getId()); + + // 이 댓글이 채택되었는지 여부 + Boolean isSelected; + if (optionalComment_choice.isEmpty()) { + isSelected = false; + } else { + isSelected = true; + } + + return isSelected; + } + + + @Override public void dislikeComment(Long postId, Long commentId, HttpServletRequest request) { Long userId = jwtTokenProvider.getCurrentUser(request); diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index f974a7a..47f883e 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -45,6 +45,7 @@ public static class commentGetRes { Boolean isMyComment; // 내가 쓴 댓글인지 여부 Boolean isPushedLike; // 좋아요 이미 눌렀는지 여부 Boolean isOwnerOfPost; // 내가 쓴 글인지 여부 + Boolean isSelected; // 채택 여부 List childrenComments; } From 5451835592c81680e479f203f42c5b200262eaea Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sun, 18 Feb 2024 01:58:52 +0900 Subject: [PATCH 203/255] =?UTF-8?q?#152=20Refactor=20:=20=ED=88=AC?= =?UTF-8?q?=ED=91=9C=20=EB=A7=88=EA=B0=90=20=EC=95=8C=EB=A6=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1,=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=A0=84=EC=86=A1?= =?UTF-8?q?=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/Application.java | 2 + .../apiPayload/code/status/ErrorStatus.java | 3 +- .../friend/spring/converter/SseConverter.java | 10 +++ .../java/friend/spring/domain/Card_poll.java | 2 +- .../java/friend/spring/domain/Gauge_poll.java | 2 +- .../friend/spring/domain/General_poll.java | 2 +- .../friend/spring/service/EmailService.java | 12 ++++ .../spring/service/SchedulerService.java | 69 +++++++++++++++++++ .../friend/spring/web/dto/SseResponseDTO.java | 11 +++ 9 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 src/main/java/friend/spring/service/SchedulerService.java diff --git a/src/main/java/friend/spring/Application.java b/src/main/java/friend/spring/Application.java index 472f691..774f7e9 100644 --- a/src/main/java/friend/spring/Application.java +++ b/src/main/java/friend/spring/Application.java @@ -3,6 +3,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.scheduling.annotation.EnableScheduling; import javax.annotation.PostConstruct; import java.time.LocalDateTime; @@ -10,6 +11,7 @@ @SpringBootApplication @EnableJpaAuditing +@EnableScheduling public class Application { @PostConstruct diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 316da34..d5b6032 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -8,7 +8,8 @@ @Getter @AllArgsConstructor -public enum ErrorStatus implements BaseErrorCode { +public enum +ErrorStatus implements BaseErrorCode { // 가장 일반적인 응답 diff --git a/src/main/java/friend/spring/converter/SseConverter.java b/src/main/java/friend/spring/converter/SseConverter.java index 120fd1e..3cf54fa 100644 --- a/src/main/java/friend/spring/converter/SseConverter.java +++ b/src/main/java/friend/spring/converter/SseConverter.java @@ -1,6 +1,7 @@ package friend.spring.converter; import friend.spring.domain.Comment; +import friend.spring.domain.Post; import friend.spring.domain.enums.AlarmType; import friend.spring.web.dto.SseResponseDTO; @@ -29,4 +30,13 @@ public static SseResponseDTO.CommentCreateResDTO toCommentCreateResDTO (Comment .commentId(comment.getId()) .build(); } + + public static SseResponseDTO.VoteFinishResDTO toVoteFinishResDTO(Post post, AlarmType alarmType){ + return SseResponseDTO.VoteFinishResDTO.builder() + .postId(post.getId()) + .alarmContent(post.getContent()) + .alarmType(alarmType.toString()) + .createdAt(post.getCreatedAt()) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/Card_poll.java b/src/main/java/friend/spring/domain/Card_poll.java index d1ccbb8..b90242c 100644 --- a/src/main/java/friend/spring/domain/Card_poll.java +++ b/src/main/java/friend/spring/domain/Card_poll.java @@ -29,7 +29,7 @@ public class Card_poll extends BaseEntity { @Builder.Default private LocalDateTime deadline= LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. - @Column(nullable = true) + @Column(nullable = false) @Builder.Default private Boolean VoteOnGoing=true; diff --git a/src/main/java/friend/spring/domain/Gauge_poll.java b/src/main/java/friend/spring/domain/Gauge_poll.java index fcb55cd..1fd7c7d 100644 --- a/src/main/java/friend/spring/domain/Gauge_poll.java +++ b/src/main/java/friend/spring/domain/Gauge_poll.java @@ -30,7 +30,7 @@ public class Gauge_poll extends BaseEntity { @Column(nullable = true) private LocalDateTime deadline= LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. - @Column(nullable = true) + @Column(nullable = false) @Builder.Default private Boolean VoteOnGoing=true; diff --git a/src/main/java/friend/spring/domain/General_poll.java b/src/main/java/friend/spring/domain/General_poll.java index 9d4bdd1..6628ee5 100644 --- a/src/main/java/friend/spring/domain/General_poll.java +++ b/src/main/java/friend/spring/domain/General_poll.java @@ -30,7 +30,7 @@ public class General_poll extends BaseEntity { @Builder.Default private LocalDateTime deadline= LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. - @Column(nullable = true) + @Column(nullable = false) @Builder.Default private Boolean VoteOnGoing=true; diff --git a/src/main/java/friend/spring/service/EmailService.java b/src/main/java/friend/spring/service/EmailService.java index e8ec00e..687212c 100644 --- a/src/main/java/friend/spring/service/EmailService.java +++ b/src/main/java/friend/spring/service/EmailService.java @@ -3,6 +3,7 @@ import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.apiPayload.handler.UserHandler; import friend.spring.config.RedisUtil; +import friend.spring.domain.Post; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.javamail.JavaMailSender; @@ -100,4 +101,15 @@ public String passwordEmail(String email) { return Integer.toString(authNumber); } + + public void voteFinishEmail(Post post){ + String setFrom = "gominchingu@gmail.com"; // email-config에 설정한 자신의 이메일 주소를 입력 + String toMail = post.getUser().getEmail(); + String title = "고민친구 투표 마감 알림 이메일 입니다."; + String content = + "회원님의 고민투표" + post.getTitle() + "이 마감되었습니다." + + "
" + + "투표를 확인해보세요!"; + mailSend(setFrom, toMail, title, content); + } } \ No newline at end of file diff --git a/src/main/java/friend/spring/service/SchedulerService.java b/src/main/java/friend/spring/service/SchedulerService.java new file mode 100644 index 0000000..91fc8fc --- /dev/null +++ b/src/main/java/friend/spring/service/SchedulerService.java @@ -0,0 +1,69 @@ +package friend.spring.service; + +import friend.spring.apiPayload.GeneralException; +import friend.spring.apiPayload.code.status.ErrorStatus; +import friend.spring.converter.AlarmConverter; +import friend.spring.converter.SseConverter; +import friend.spring.domain.*; +import friend.spring.domain.enums.AlarmType; +import friend.spring.repository.AlarmRepository; +import friend.spring.repository.PostRepository; +import friend.spring.web.dto.SseResponseDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class SchedulerService { + + private final PostRepository postRepository; + private final EmailService emailService; + private final SseService notificationService; + private final AlarmRepository alarmRepository; + // 투표 마감 + // (1시간마다 검사해서 투표 마감 날짜가 지나면 닫히도록 할 예정) + @Transactional + @Async + @Scheduled(cron = "0 0/1 * * * *", zone = "Asia/Seoul") // 매 분마다 실행 -> 매 시간마다 실행으로 변경 예정 + public void deleteVote() { + List postList = postRepository.findAll(); + if (postList.isEmpty()){ + throw new GeneralException(ErrorStatus.POST_NOT_FOUND); + } + LocalDateTime now = LocalDateTime.now(); + for (Post post : postList) { + Gauge_poll gaugePoll = post.getGaugePoll(); + Card_poll cardPoll = post.getCardPoll(); + General_poll generalPoll = post.getGeneralPoll(); + if (gaugePoll != null && gaugePoll.getDeadline().isBefore(now) && gaugePoll.getVoteOnGoing()) { + gaugePoll.setVoteOnGoing(false); + getData(post); + } + if (cardPoll != null && cardPoll.getDeadline().isBefore(now) && cardPoll.getVoteOnGoing()) { + cardPoll.setVoteOnGoing(false); + getData(post); + } + if (generalPoll != null && generalPoll.getDeadline().isBefore(now) && generalPoll.getVoteOnGoing()) { + generalPoll.setVoteOnGoing(false); + getData(post); + } + } + + } + + private void getData(Post post) { + SseResponseDTO.VoteFinishResDTO voteFinishResDTO = SseConverter.toVoteFinishResDTO(post, AlarmType.VOTE_FINISH); + Alarm newAlarm = AlarmConverter.toAlarm(voteFinishResDTO.getAlarmContent(), AlarmType.VOTE_FINISH, post, post.getUser(), null); + emailService.voteFinishEmail(post); + alarmRepository.saveAndFlush(newAlarm); + notificationService.customNotify(post.getUser().getId(), voteFinishResDTO, post.getTitle(), AlarmType.VOTE_FINISH.toString()); + } + + +} diff --git a/src/main/java/friend/spring/web/dto/SseResponseDTO.java b/src/main/java/friend/spring/web/dto/SseResponseDTO.java index 52b9d8c..4096039 100644 --- a/src/main/java/friend/spring/web/dto/SseResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/SseResponseDTO.java @@ -22,4 +22,15 @@ public static class CommentCreateResDTO { Long commentId; LocalDateTime createdAt; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class VoteFinishResDTO{ + String alarmContent; + String alarmType; + Long postId; + LocalDateTime createdAt; + } } From 27762325e62cabae0efe067a24e22352fb206499 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 18 Feb 2024 03:55:19 +0900 Subject: [PATCH 204/255] =?UTF-8?q?#155=20Refactor:=20=ED=88=AC=ED=91=9C/?= =?UTF-8?q?=EA=B8=80=20=EC=9E=91=EC=84=B1=20=EC=8B=9C=20=ED=8F=AC=EC=9D=B8?= =?UTF-8?q?=ED=8A=B8=20amount=20=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/service/PostServiceImpl.java | 6 +++--- src/main/java/friend/spring/service/VoteServiceImpl.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index a09de34..44df11d 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -125,7 +125,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque } user.setPoint(user.getPoint() - request.getPoint()); Point newPoint=Point.builder() - .amount(user.getPoint()) + .amount(request.getPoint() * -1) // 차감이므로 -1 곱해서 음수로 변환 .content("일반 투표 작성에 대한 "+request.getPoint()+" 포인트 차감") .build(); newPoint.setUser(user); @@ -152,7 +152,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque } user.setPoint(user.getPoint() - request.getPoint()); Point newPoint=Point.builder() - .amount(user.getPoint()) + .amount(request.getPoint() * -1) .content("게이지 투표 등록에 대한 "+request.getPoint()+" 포인트 차감") .build(); newPoint.setUser(user); @@ -182,7 +182,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque } user.setPoint(user.getPoint() - request.getPoint()); Point newPoint=Point.builder() - .amount(user.getPoint()) + .amount(request.getPoint() * -1) .content("카드 투표 등록에 대한 "+request.getPoint()+" 포인트 차감") .build(); newPoint.setUser(user); diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index 4284adf..6805b26 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -68,7 +68,7 @@ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request user.setPoint(user.getPoint() + 5); Point newPoint=Point.builder() - .amount(user.getPoint()) + .amount(5) .content("일반 투표에 대한 "+5+" 포인트 획득") .build(); newPoint.setUser(user); @@ -106,7 +106,7 @@ public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long user.setPoint(user.getPoint() + 5); Point newPoint=Point.builder() - .amount(user.getPoint()) + .amount(5) .content("게이지 투표에 대한 "+5+" 포인트 획득") .build(); newPoint.setUser(user); @@ -163,7 +163,7 @@ public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request,Long Pos user.setPoint(user.getPoint() + 5); Point newPoint=Point.builder() - .amount(user.getPoint()) + .amount(5) .content("카드 투표에 대한 "+5+" 포인트 획득") .build(); newPoint.setUser(user); From 985b9b07330be1c1259258f693c0c92b5215a5e6 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sun, 18 Feb 2024 05:10:50 +0900 Subject: [PATCH 205/255] =?UTF-8?q?#152=20Refactor=20:=20=ED=88=AC?= =?UTF-8?q?=ED=91=9C=20=EB=A7=88=EA=B0=90=20=EC=95=8C=EB=A6=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1,=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=A0=84=EC=86=A1?= =?UTF-8?q?=20API=20=EA=B5=AC=ED=98=84=20+=20DEFAULT=5FTIMEOUT=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/service/SseService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/service/SseService.java b/src/main/java/friend/spring/service/SseService.java index 8503cfc..dcc330c 100644 --- a/src/main/java/friend/spring/service/SseService.java +++ b/src/main/java/friend/spring/service/SseService.java @@ -13,7 +13,7 @@ @RequiredArgsConstructor public class SseService { // 기본 타임아웃 설정 - private static final Long DEFAULT_TIMEOUT = 60L * 1000 * 60; // 1시간 + private static final Long DEFAULT_TIMEOUT = 60L * 1000 * 60 * 48; // 1시간 * 48 -> 데모데이 까지만! private final EmitterRepository emitterRepository; private final JwtTokenProvider jwtTokenProvider; From 64d4262cab2e420370cf2d9574219594ed931bc8 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Sun, 18 Feb 2024 13:47:13 +0900 Subject: [PATCH 206/255] =?UTF-8?q?=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EC=9E=AC=EC=84=A4=EC=A0=95=20=EC=99=84=EB=A3=8C,accessToken?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EC=8B=9C=EA=B0=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 1 + .../spring/converter/UserConverter.java | 6 +- .../spring/security/JwtTokenProvider.java | 2 +- .../friend/spring/service/EmailService.java | 1 + .../friend/spring/service/UserService.java | 4 +- .../spring/service/UserServiceImpl.java | 66 ++++++++++++++----- .../web/controller/UserRestController.java | 27 ++++++-- .../friend/spring/web/dto/UserRequestDTO.java | 13 +++- .../spring/web/dto/UserResponseDTO.java | 8 +++ 9 files changed, 105 insertions(+), 23 deletions(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 10454b8..343aeeb 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -26,6 +26,7 @@ public enum ErrorStatus implements BaseErrorCode { INCORRECT_CODE(HttpStatus.UNAUTHORIZED, "USER4005", "인증 코드가 일치하지 않습니다."), EMPTY_JWT(HttpStatus.BAD_REQUEST, "USER4006", "JWT를 입력해주세요."), INVALID_JWT(HttpStatus.UNAUTHORIZED, "USER4007", "유효하지 않은 JWT입니다."), + INVALID_PASSWORD_FORMAT(HttpStatus.NOT_ACCEPTABLE,"USER4077","비밀번호 형식에 맞지 않습니다."), PASSWORD_INCORRECT(HttpStatus.NOT_FOUND, "USER4008", "비밀번호가 틀렸습니다."), PASSWORD_CHECK_INCORRECT(HttpStatus.NOT_FOUND, "USER4009", "확인 비밀번호가 일치하지 않습니다."), RTK_INCORREXT(HttpStatus.UNAUTHORIZED,"USER4100","RefreshToken값을 확인해주세요."), diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 7425b24..c691ef2 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -204,5 +204,9 @@ public static User KakaoUser( .email(kakaoProfile.getKakao_account().getEmail()).build(); } - + public static UserResponseDTO.PasswordUpdateRes toUpdatePassword(User user){ + return UserResponseDTO.PasswordUpdateRes.builder() + .newPassword(user.getEmail()) + .build(); + } } diff --git a/src/main/java/friend/spring/security/JwtTokenProvider.java b/src/main/java/friend/spring/security/JwtTokenProvider.java index ca7b91a..f035be1 100644 --- a/src/main/java/friend/spring/security/JwtTokenProvider.java +++ b/src/main/java/friend/spring/security/JwtTokenProvider.java @@ -54,7 +54,7 @@ protected void init() { // JWT Access 토큰 생성 public TokenDTO createAccessToken(String email) { // 토큰 유효시간 30분 - long tokenValidTime =2 * 60 * 60 * 1000L; + long tokenValidTime =48 * 60 * 60 * 1000L; Optional user = userRepository.findByEmail(email); diff --git a/src/main/java/friend/spring/service/EmailService.java b/src/main/java/friend/spring/service/EmailService.java index e8ec00e..cde30a9 100644 --- a/src/main/java/friend/spring/service/EmailService.java +++ b/src/main/java/friend/spring/service/EmailService.java @@ -100,4 +100,5 @@ public String passwordEmail(String email) { return Integer.toString(authNumber); } + } \ No newline at end of file diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index cb52582..93f50b6 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -2,6 +2,7 @@ import friend.spring.domain.Level; import friend.spring.domain.User; +import friend.spring.web.dto.MyPageRequestDTO; import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; @@ -18,6 +19,7 @@ public interface UserService { Integer pointCheck(Long id); Level nextLevel(Long id); String logout(HttpServletRequest request); - List reissue(HttpServletRequest request); + User updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwordUpdateReq); + String getEmail(HttpServletRequest request); } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 7ac5b29..7ab9640 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -11,6 +11,7 @@ import friend.spring.security.JwtTokenProvider; import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; +import io.jsonwebtoken.io.IOException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; @@ -25,6 +26,7 @@ import java.util.concurrent.TimeUnit; import static friend.spring.apiPayload.code.status.ErrorStatus.*; +import static java.util.regex.Pattern.matches; @Slf4j @Service @@ -33,11 +35,12 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; - + private final EmailService emailService; private final LevelRepository levelRepository; private final JwtTokenProvider jwtTokenProvider; private final RedisTemplate redisTemplate; + static final String PASSWORD_PATTERN = "^(?=.*[a-z])(?=.*[A-Z]+)(?=.*\\d)(?=.*[!@#$%^&*]).{8,64}$"; BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @@ -76,7 +79,7 @@ public User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest) {//회원 @Override public Level nextLevel(Long id) { Optional user = userRepository.findById(id); - if(user.isEmpty()) { + if (user.isEmpty()) { throw new UserHandler(USER_NOT_FOUND); } Long curId = user.get().getLevel().getId(); @@ -88,14 +91,14 @@ public Level nextLevel(Long id) { @Override public List reissue(HttpServletRequest request) { String rtk = request.getHeader("rtk"); - System.out.println("reissue함수실행 rtk: "+rtk); + System.out.println("reissue함수실행 rtk: " + rtk); // refresh token 유효성 검증 if (!jwtTokenProvider.validateToken(rtk)) throw new GeneralException(INVALID_JWT); String email = jwtTokenProvider.getTokenSub(rtk); - System.out.println("rtk subject인 email: "+email); + System.out.println("rtk subject인 email: " + email); // Redis에서 email 기반으로 저장된 refresh token 값 가져오기 String refreshToken = (String) redisTemplate.opsForValue().get("RT:" + email); @@ -104,7 +107,7 @@ public List reissue(HttpServletRequest request) { throw new GeneralException(RTK_INCORREXT); } - if(!refreshToken.equals(rtk)) { + if (!refreshToken.equals(rtk)) { throw new GeneralException(RTK_INCORREXT); } @@ -114,18 +117,18 @@ public List reissue(HttpServletRequest request) { TokenDTO newAccessToken = jwtTokenProvider.createAccessToken(email); tokenDTOList.add(newRefreshToken); tokenDTOList.add(newAccessToken); - System.out.println("Access Token, Refresh Token 재발행: " +tokenDTOList); + System.out.println("Access Token, Refresh Token 재발행: " + tokenDTOList); // Redis에 refresh token 업데이트 - redisTemplate.opsForValue().set("RT:"+email,newRefreshToken.getToken(),newRefreshToken.getTokenExpriresTime().getTime(),TimeUnit.MILLISECONDS); + redisTemplate.opsForValue().set("RT:" + email, newRefreshToken.getToken(), newRefreshToken.getTokenExpriresTime().getTime(), TimeUnit.MILLISECONDS); return tokenDTOList; } //로그인 - public List login(UserRequestDTO.UserLoginRequest userLoginRequest)throws GeneralException{ + public List login(UserRequestDTO.UserLoginRequest userLoginRequest) throws GeneralException { User user = userRepository.findByEmail(userLoginRequest.getEmail()) - .orElseThrow(()-> new GeneralException(USERS_NOT_FOUND_EMAIL));//가입 안된 이메일 + .orElseThrow(() -> new GeneralException(USERS_NOT_FOUND_EMAIL));//가입 안된 이메일 if (!encoder.matches(userLoginRequest.getPassword(), user.getPassword())) { throw new GeneralException(PASSWORD_INCORRECT); //비밀번호 불일치 } @@ -136,7 +139,7 @@ public List login(UserRequestDTO.UserLoginRequest userLoginRequest)thr // login 시 Redis에 RT:gominchingy@gmail.com(key): --refresh token실제값--(value) 형태로 refresh 토큰 저장하기 // opsForValue() : set을 통해 key,value값 저장하고 get(key)통해 value가져올 수 있음. // refreshToken.getTokenExpriresTime().getTime() : 리프레시 토큰의 만료시간이 지나면 해당 값 자동 삭제 - redisTemplate.opsForValue().set("RT:"+user.getEmail(),refreshToken.getToken(), refreshToken.getTokenExpriresTime().getTime(), TimeUnit.MILLISECONDS); + redisTemplate.opsForValue().set("RT:" + user.getEmail(), refreshToken.getToken(), refreshToken.getTokenExpriresTime().getTime(), TimeUnit.MILLISECONDS); List tokenDTOList = new ArrayList<>(); tokenDTOList.add(accessToken); @@ -148,11 +151,11 @@ public List login(UserRequestDTO.UserLoginRequest userLoginRequest)thr @Override // 로그아웃 - userIdx - public String logout(HttpServletRequest request) { + public String logout(HttpServletRequest request) { Long userIdx = jwtTokenProvider.getCurrentUser(request); - System.out.println("getCurrentUser()로 가져온 userIdx : "+userIdx); + System.out.println("getCurrentUser()로 가져온 userIdx : " + userIdx); User user = userRepository.findById(userIdx) .orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); @@ -172,10 +175,43 @@ public String logout(HttpServletRequest request) { @Override public Integer pointCheck(Long id) { - User user=userRepository.findById(id) - .orElseThrow(()->new RuntimeException("\""+id+"\"해당 유저가 없습니다")); + User user = userRepository.findById(id) + .orElseThrow(() -> new RuntimeException("\"" + id + "\"해당 유저가 없습니다")); return user.getPoint(); } -} + private boolean isValidPassword(String password) { + return password.matches(PASSWORD_PATTERN); + } + + //비밀번호 변경 + public User updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwordUpdateReq) throws GeneralException { + User user = userRepository.findByEmail(email).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + + String newPassword = passwordUpdateReq.getNewPassword(); + + if (!isValidPassword(newPassword)) { + throw new GeneralException(INVALID_PASSWORD_FORMAT); + } + if (!passwordUpdateReq.getNewPassword().equals(passwordUpdateReq.getNewPasswordCheck())) { + throw new GeneralException(ErrorStatus.PASSWORD_CHECK_INCORRECT); + } + + // 새로운 비밀번호가 null이 아닌 경우, 사용자의 비밀번호를 새로운 값으로 업데이트 + if (newPassword != null) { + user.setPassword(encoder.encode(newPassword)); + } + userRepository.save(user); + return user; + } + // Request 의 Header 에서 email 값 추출 "email" : "gominchingu@gmail.com" + public String getEmail(HttpServletRequest request) { + return request.getHeader("email"); + } +} +// +// // Request 의 Header 에서 access token 값 추출 "atk" : "token--" +// public String resolveAccessToken(HttpServletRequest request) { +// return request.getHeader("atk"); +// } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index e60ea98..91f3fd3 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -2,6 +2,7 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.apiPayload.GeneralException; +import friend.spring.converter.MyPageConverter; import friend.spring.converter.UserConverter; import friend.spring.domain.Comment; import friend.spring.domain.Level; @@ -14,9 +15,7 @@ import friend.spring.service.PostService; import friend.spring.service.UserService; import friend.spring.service.*; -import friend.spring.web.dto.TokenDTO; -import friend.spring.web.dto.UserRequestDTO; -import friend.spring.web.dto.UserResponseDTO; +import friend.spring.web.dto.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; @@ -224,5 +223,25 @@ public ApiResponse> kakaoLogin(@RequestParam("code") String code) return ApiResponse.onSuccess(authService.kakaoLogin(code)); } -} + + @PatchMapping(value = "/updatePassword") + @Operation(summary = "비밀번호 재설정 API", description = "(비밀번호 재설정 이메일 인증후) 비밀번호를 변경하는 API") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. ") + }) + @Parameters({ + @Parameter(name = "email", description = "RequestHeader - 비밀번호를 바꾸고자 하는 사용자의 email") + }) + public ApiResponse updatePassword( + @RequestHeader(name = "email") String mail, + HttpServletRequest request, + @RequestBody @Valid UserRequestDTO.PasswordUpdateReq passwordUpdateReq){ + String email = userService.getEmail(request); + User updPassword = userService.updatePassword(email, passwordUpdateReq); + + return ApiResponse.onSuccess(UserConverter.toUpdatePassword(updPassword)); + + } + +} diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index ad34e4f..897dded 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -122,4 +122,15 @@ public static class PasswordEmailSendCheckReq { private String name; private String authNum; } -} +//비밀번호 변경 + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Setter + public static class PasswordUpdateReq { + + @NotEmpty(message = "변경할 비밀번호를 입력해 주세요") + private String newPassword; + private String newPasswordCheck; + } +} \ No newline at end of file diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index 41e0774..021fd62 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -134,4 +134,12 @@ public static class UserSummaryInfo { String nickname; String image; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class PasswordUpdateRes{ + String newPassword; + } } From 6b7ce6d739b419294fb29ad12e91e553d3552637 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Sun, 18 Feb 2024 13:58:43 +0900 Subject: [PATCH 207/255] =?UTF-8?q?=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8?= =?UTF-8?q?=EC=9E=AC=EC=84=A4=EC=A0=95=20converter=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/UserConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index c691ef2..cdf3c72 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -206,7 +206,7 @@ public static User KakaoUser( } public static UserResponseDTO.PasswordUpdateRes toUpdatePassword(User user){ return UserResponseDTO.PasswordUpdateRes.builder() - .newPassword(user.getEmail()) + .newPassword(user.getPassword()) .build(); } } From 88130d2c4ff5249e19731fcbc845b65d904eab21 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sun, 18 Feb 2024 22:33:56 +0900 Subject: [PATCH 208/255] =?UTF-8?q?#152=20Refactor=20:=20=ED=88=AC?= =?UTF-8?q?=ED=91=9C=20=EB=A7=88=EA=B0=90=20=EC=95=8C=EB=A6=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1,=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=A0=84=EC=86=A1?= =?UTF-8?q?=20API=20=EA=B5=AC=ED=98=84=20+=20DEFAULT=5FTIMEOUT=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=EC=88=98=EC=A0=95,=20response=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/MyPageConverter.java | 1 + src/main/java/friend/spring/web/dto/MyPageResponseDTO.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index 2a592ef..4681ec8 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -20,6 +20,7 @@ public class MyPageConverter { public static MyPageResponseDTO.CategoryResDTO toCategoryResDTO(Category category){ return MyPageResponseDTO.CategoryResDTO.builder() + .categoryId(category.getId()) .category(category.getName()) .build(); } diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index 1b949bc..5a23da1 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -19,6 +19,7 @@ public class MyPageResponseDTO { @NoArgsConstructor @AllArgsConstructor public static class CategoryResDTO{ + Long categoryId; String category; } From f6bf8dd7ba1d2a054020822d94af2c34a5b9d95a Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 19 Feb 2024 01:41:25 +0900 Subject: [PATCH 209/255] =?UTF-8?q?#155=20Refactor:=20=EC=9D=BC=EB=B0=98/?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=20=ED=88=AC=ED=91=9C=20allCandidatePercent?= =?UTF-8?q?=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EB=A6=AC=ED=84=B4=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 108 ++++++++++++++++++ .../spring/repository/CommentRepository.java | 2 - .../spring/service/SchedulerService2.java | 35 ++++++ 3 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 src/main/java/friend/spring/service/SchedulerService2.java diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 0fd3707..b3614a4 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -923,6 +923,14 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); + allCandidatePercent=post.getGeneralPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId=candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + return PostResponseDTO.PollPostGetResponse.builder() .onGoing(true) .isVoted(true) @@ -946,6 +954,48 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .build(); } + + // 총 투표수 계산 + long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + //1등 투표 계산 + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .max(); + + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + topCandidateList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + + topCandidatePercent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + allCandidatePercent=post.getGeneralPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId=candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + return PostResponseDTO.PollPostGetResponse.builder() .onGoing(true) .isVoted(false) @@ -957,6 +1007,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) .like(likeCount) .comment(commentCount) .isLike(isLike) @@ -1221,6 +1274,15 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); + + allCandidatePercent=post.getCardPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId=candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + return PostResponseDTO.PollPostGetResponse.builder() .onGoing(true) .isVoted(true) @@ -1244,6 +1306,49 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .build(); } + + // 총 투표수 계산 + long totalVotes = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + //1등 투표 계산 + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .max(); + + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + topCandidateList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + + topCandidatePercent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + allCandidatePercent=post.getCardPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId=candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + return PostResponseDTO.PollPostGetResponse.builder() .onGoing(true) .isVoted(false) @@ -1255,6 +1360,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) .like(likeCount) .comment(commentCount) .isLike(isLike) diff --git a/src/main/java/friend/spring/repository/CommentRepository.java b/src/main/java/friend/spring/repository/CommentRepository.java index 96c8a1c..943aaa5 100644 --- a/src/main/java/friend/spring/repository/CommentRepository.java +++ b/src/main/java/friend/spring/repository/CommentRepository.java @@ -13,6 +13,4 @@ public interface CommentRepository extends JpaRepository { List findByPostIdAndParentCommentIsNull(Long postId); Page findAllByUser(User user, PageRequest pageRequest); - - Integer countByPostId(Long postId); } diff --git a/src/main/java/friend/spring/service/SchedulerService2.java b/src/main/java/friend/spring/service/SchedulerService2.java new file mode 100644 index 0000000..0df9f26 --- /dev/null +++ b/src/main/java/friend/spring/service/SchedulerService2.java @@ -0,0 +1,35 @@ +package friend.spring.service; + +import friend.spring.domain.Point; +import friend.spring.repository.PointRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; + +@Service +@Slf4j +@RequiredArgsConstructor +public class SchedulerService2 { + private final PointRepository pointRepository; + +// // Point 내역 합계 값과 User 엔티티의 point 값이 일치하는지 주기적으로 확인 +// @Transactional +// @Async +// @Scheduled(cron = "0 0 0 * * *", zone = "Asia/Seoul") // 매일 오전 0시에 실행 +// public void checkPoint() { +// List pointList = pointRepository.findAll(); +// for (Point point : pointList) { +// +// } +// +// +// chatRoomRepository.disabledSafeUpdates(); // safe update 임시 해제 (여러 열 수정 가능하도록) +// chatRoomRepository.deleteChatRoom(); +// } +} From 69f027c81b5d4b68744773025cef213f9cb562be Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 19 Feb 2024 07:08:58 +0900 Subject: [PATCH 210/255] =?UTF-8?q?#155=20Refactor:=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=ED=8C=8C=EC=9D=BC=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20MultipartFile=20->=20Base64=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/Base64Decoder.java | 67 +++++++++++++++++++ .../friend/spring/service/PostService.java | 11 ++- .../spring/service/PostServiceImpl.java | 19 +++--- .../java/friend/spring/service/S3Service.java | 33 +++++++++ .../web/controller/PostRestController.java | 19 ++---- .../spring/web/dto/CandidateRequestDTO.java | 15 +++++ .../friend/spring/web/dto/PostRequestDTO.java | 9 +-- 7 files changed, 136 insertions(+), 37 deletions(-) create mode 100644 src/main/java/friend/spring/converter/Base64Decoder.java create mode 100644 src/main/java/friend/spring/web/dto/CandidateRequestDTO.java diff --git a/src/main/java/friend/spring/converter/Base64Decoder.java b/src/main/java/friend/spring/converter/Base64Decoder.java new file mode 100644 index 0000000..d181c43 --- /dev/null +++ b/src/main/java/friend/spring/converter/Base64Decoder.java @@ -0,0 +1,67 @@ +package friend.spring.converter; + +import org.springframework.web.multipart.MultipartFile; +import java.io.*; +import java.util.Base64; + +public class Base64Decoder { + + public static MultipartFile decodeBase64ToMultipartFile(String base64String) throws IOException { + // Base64 문자열을 디코딩하여 byte 배열로 변환 + byte[] decodedBytes = Base64.getDecoder().decode(base64String); + + // 디코딩된 byte 배열을 이용하여 MultipartFile 생성 + MultipartFile multipartFile = createMultipartFile(decodedBytes); + + return multipartFile; + } + + private static MultipartFile createMultipartFile(byte[] content) throws IOException { + // MultipartFile을 구현한 클래스를 사용하여 MultipartFile 생성 + return new MultipartFile() { + @Override + public String getName() { + return null; + } + + @Override + public String getOriginalFilename() { + // 임의의 파일 이름 또는 고정된 확장자를 사용할 수 있습니다. + return "example.jpg"; + } + + @Override + public String getContentType() { + // 이미지 타입에 맞게 Content-Type 설정 + return "image/jpeg"; // 예시로 JPEG 이미지로 설정 + } + + @Override + public boolean isEmpty() { + return content.length == 0; + } + + @Override + public long getSize() { + return content.length; + } + + @Override + public byte[] getBytes() throws IOException { + return content; + } + + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(content); + } + + @Override + public void transferTo(File dest) throws IOException, IllegalStateException { + try (OutputStream os = new FileOutputStream(dest)) { + os.write(content); + } + } + }; + } +} diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index fd47bc5..042b0fe 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -6,16 +6,13 @@ import friend.spring.domain.User; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; -import friend.spring.web.dto.PollOptionDTO; +import friend.spring.web.dto.CandidateRequestDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; import org.springframework.data.domain.Page; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RequestPart; -import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; -import java.util.List; +import java.io.IOException; public interface PostService { void checkPost(Boolean flag); @@ -25,9 +22,9 @@ public interface PostService { void checkPostLike(Boolean flag); - Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2, List file); + Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2); - Candidate createCandidate(Long postId, String optionString, MultipartFile optionImg, HttpServletRequest request2); + Candidate createCandidate(Long postId, CandidateRequestDTO.AddCandidateRequestDTO request, HttpServletRequest request2) throws IOException; Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user); diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 44df11d..b075605 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -18,9 +18,8 @@ import org.springframework.data.domain.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - +import java.io.IOException; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import javax.servlet.http.HttpServletRequest; @@ -94,7 +93,7 @@ public void checkPostScrap(Boolean flag) { @Override @Transactional - public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2, List file) { + public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2) { Long userId = jwtTokenProvider.getCurrentUser(request2); Post newPost= PostConverter.toPost(request); @@ -103,8 +102,8 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque newPost.setUser(user); // 글 첨부파일 사진 저장 - if (file != null) { - s3Service.uploadPostImages(file, S3ImageType.POST, newPost); + if (request.getFileBase64List() != null) { + s3Service.uploadPostImagesBase64(request.getFileBase64List(), S3ImageType.POST, newPost); } LocalDateTime deadline=request.getDeadline(); if(request.getDeadline()==null){ @@ -218,7 +217,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque @Override @Transactional - public Candidate createCandidate(Long postId, String optionString, MultipartFile optionImg, HttpServletRequest request2) { + public Candidate createCandidate(Long postId, CandidateRequestDTO.AddCandidateRequestDTO request, HttpServletRequest request2) throws IOException { Post newPost = postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); Long userId = jwtTokenProvider.getCurrentUser(request2); @@ -227,18 +226,18 @@ public Candidate createCandidate(Long postId, String optionString, MultipartFile this.checkPostWriterUser(false); } - if (!(!optionString.isEmpty() && optionString.length() < 30)) { // 이 글을 쓴 사용자인지 검증 + if (!(!request.getOptionString().isEmpty() && request.getOptionString().length() < 30)) { throw new GeneralException(CANDIDATE_TEXT_LIMIT); } Candidate candidate = Candidate.builder() - .name(optionString) + .name(request.getOptionString()) .build(); candidateRepository.save(candidate); - if (optionImg != null) { - File candidateFile = s3Service.uploadSingleImage(optionImg, S3ImageType.CANDIDATE, null, candidate); + if (request.getOptionImg() != null) { + File candidateFile = s3Service.uploadSingleImageBase64(request.getOptionImg(), S3ImageType.CANDIDATE, null, candidate); candidate.setFile(candidateFile); } diff --git a/src/main/java/friend/spring/service/S3Service.java b/src/main/java/friend/spring/service/S3Service.java index 5bdac03..2bcf864 100644 --- a/src/main/java/friend/spring/service/S3Service.java +++ b/src/main/java/friend/spring/service/S3Service.java @@ -1,6 +1,7 @@ package friend.spring.service; import friend.spring.aws.s3.AmazonS3Manager; +import friend.spring.converter.Base64Decoder; import friend.spring.converter.FileConverter; import friend.spring.domain.*; import friend.spring.domain.enums.S3ImageType; @@ -11,6 +12,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -35,6 +37,23 @@ public List uploadPostImages(List multipartFiles, S3ImageTy return fileList; } + public List uploadPostImagesBase64(List fileBase64List, S3ImageType type, Post post) { + List fileList = new ArrayList<>(); + // forEach 구문을 통해 multipartFiles 리스트로 넘어온 파일들을 순차적으로 fileList 에 추가 + fileBase64List.forEach(base64String -> { + MultipartFile file = null; + try { + file = Base64Decoder.decodeBase64ToMultipartFile(base64String); + String pictureUrl = s3Manager.uploadFile(s3Manager.generatePostKeyName(createFileName()), file); + File newFile = fileRepository.save(FileConverter.toFile(pictureUrl, null, post, null)); + fileList.add(newFile); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + return fileList; + } + public File uploadSingleImage(MultipartFile file, S3ImageType type, User user, Candidate candidate) { File newFile; if (type == S3ImageType.USER && user != null) { // 사용자 프로필 이미지인 경우 @@ -47,6 +66,20 @@ public File uploadSingleImage(MultipartFile file, S3ImageType type, User user, C return newFile; } + public File uploadSingleImageBase64(String fileBase64, S3ImageType type, User user, Candidate candidate) throws IOException { + File newFile; + MultipartFile file = Base64Decoder.decodeBase64ToMultipartFile(fileBase64); + + if (type == S3ImageType.USER && user != null) { // 사용자 프로필 이미지인 경우 + String pictureUrl = s3Manager.uploadFile(s3Manager.generateUserKeyName(createFileName()), file); + newFile = fileRepository.save(FileConverter.toFile(pictureUrl, user, null, null)); + } else { // 후보 이미지인 경우 + String pictureUrl = s3Manager.uploadFile(s3Manager.generateCandidateKeyName(createFileName()), file); + newFile = fileRepository.save(FileConverter.toFile(pictureUrl, null, null, candidate)); + } + return newFile; + } + // 유저 프로필 사진 변경(이미 데이터가 있는 경우) @Transactional public File editSingleImage(MultipartFile file, User user) { diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 2b2e998..abd4319 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -11,8 +11,6 @@ import friend.spring.web.dto.*; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; @@ -22,12 +20,10 @@ import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; -import java.util.List; -import java.util.Optional; +import java.io.IOException; @RestController @RequiredArgsConstructor @@ -55,14 +51,14 @@ public class PostRestController { }) public ApiResponse join(@RequestPart(value = "request") @Valid PostRequestDTO.AddPostDTO request, - @RequestPart(value = "file", required = false) List file, +// @RequestPart(value = "file", required = false) List file, @RequestHeader("atk") String atk, HttpServletRequest request2){ - Post post= postService.joinPost(request,request2, file); + Post post= postService.joinPost(request,request2); return ApiResponse.onSuccess(PostConverter.toAddPostResultDTO(post)); } - @PostMapping(value = "/{post-id}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @PostMapping(value = "/{post-id}") @Operation(summary = "후보 생성 API", description = "후보를 생성합니다.(글 작성 API 호출 후 postId 응답 받으시면, 후보 개수 만큼 바로 호출해주세요!)") @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @@ -70,11 +66,10 @@ public ApiResponse join(@RequestPart(value = " }) public ApiResponse createCandidate( @PathVariable(name="post-id") Long postId, - @RequestParam String optionString, - @RequestParam(required = false) MultipartFile optionImg, + @RequestBody CandidateRequestDTO.AddCandidateRequestDTO request, @RequestHeader("atk") String atk, - HttpServletRequest request2) { - Candidate candidate = postService.createCandidate(postId, optionString, optionImg,request2); + HttpServletRequest request2) throws IOException { + Candidate candidate = postService.createCandidate(postId, request, request2); return ApiResponse.onSuccess(CandidateConverter.toAddCandidateResultDTO(candidate)); } diff --git a/src/main/java/friend/spring/web/dto/CandidateRequestDTO.java b/src/main/java/friend/spring/web/dto/CandidateRequestDTO.java new file mode 100644 index 0000000..260d147 --- /dev/null +++ b/src/main/java/friend/spring/web/dto/CandidateRequestDTO.java @@ -0,0 +1,15 @@ +package friend.spring.web.dto; + +import lombok.*; + +public class CandidateRequestDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class AddCandidateRequestDTO { + String optionString; + String optionImg; + } +} diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index 7b32508..556b3e5 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -1,8 +1,5 @@ package friend.spring.web.dto; - -import friend.spring.domain.Category; -import friend.spring.domain.Post; import friend.spring.validation.annotation.ContentTextLimit; import friend.spring.validation.annotation.DeadlineLimit; import friend.spring.validation.annotation.TitleTextLimit; @@ -10,13 +7,8 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import net.bytebuddy.asm.Advice; -import org.apache.tomcat.jni.Poll; -import org.springframework.web.multipart.MultipartFile; -import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; -import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.List; @@ -37,6 +29,7 @@ public static class AddPostDTO{ @DeadlineLimit LocalDateTime deadline; Integer point; + List fileBase64List; } @Getter public static class ReviewPostGetDTO{ From c0a7e2269129888800fbdf47574abefee223e973 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 19 Feb 2024 07:27:04 +0900 Subject: [PATCH 211/255] =?UTF-8?q?#155=20Refactor:=20=EA=B8=80=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=EC=97=90=EC=84=9C=20MULTIPART=5FFORM=5FDATA?= =?UTF-8?q?=5FVALUE=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/web/controller/PostRestController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index abd4319..1bd48ca 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -34,7 +34,7 @@ public class PostRestController { private final PostQueryService postQueryService; private final PostRepository postRepository; private final JwtTokenService jwtTokenService; - @PostMapping(value = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @PostMapping(value = "/") @Operation(summary = "글 작성 API", description = "글을 추가 합니다.") @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), From 3976efd3e02287582195abfb0e68fee1c1617c7d Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 19 Feb 2024 16:45:26 +0900 Subject: [PATCH 212/255] =?UTF-8?q?#155=20Refactor:=20=EA=B8=80=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=EC=97=90=EC=84=9C=20MULTIPART=5FFORM=5FDATA?= =?UTF-8?q?=5FVALUE=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/web/controller/PostRestController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 1bd48ca..abd4319 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -34,7 +34,7 @@ public class PostRestController { private final PostQueryService postQueryService; private final PostRepository postRepository; private final JwtTokenService jwtTokenService; - @PostMapping(value = "/") + @PostMapping(value = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @Operation(summary = "글 작성 API", description = "글을 추가 합니다.") @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), From 584bb0bc4d230659540bb6a5ca7c863f8271c9de Mon Sep 17 00:00:00 2001 From: ls-rain Date: Thu, 22 Feb 2024 20:33:45 +0900 Subject: [PATCH 213/255] =?UTF-8?q?#164=20Refactor=20:=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20response=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20#164?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/CommentConverter.java | 1 + src/main/java/friend/spring/converter/MyPageConverter.java | 1 + src/main/java/friend/spring/converter/PostConverter.java | 1 + src/main/java/friend/spring/web/dto/CommentResponseDTO.java | 1 + src/main/java/friend/spring/web/dto/MyPageResponseDTO.java | 1 + src/main/java/friend/spring/web/dto/PostResponseDTO.java | 1 + 6 files changed, 6 insertions(+) diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index 20fac64..59ccfd0 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -106,6 +106,7 @@ public static CommentResponseDTO.commentSelectRes toCommentSelectRes(Comment_cho } public static CommentResponseDTO.myCommentRes toMyCommentResDTO(Comment comment){ return CommentResponseDTO.myCommentRes.builder() + .postId(comment.getPost().getId()) .nickName(comment.getUser().getNickname()) .createdAt(comment.getCreatedAt()) .content(comment.getContent()) diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index 4681ec8..84052bf 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -115,6 +115,7 @@ public static MyPageResponseDTO.SavedPostCategoryDetailRes toSavedPostCategoryDe long diffTime = post.getCreatedAt().until(LocalDateTime.now(), ChronoUnit.DAYS); // now보다 이후면 +, 전이면 - return MyPageResponseDTO.SavedPostCategoryDetailRes.builder() + .postId(post.getId()) .ago(diffTime) .title(post.getTitle()) .content(post.getContent()) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index b3614a4..28ef3dc 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -1546,6 +1546,7 @@ public static ParentPostDTO.ParentPostGetListDTO parentPostGetListDTO(Page public static PostResponseDTO.MyPostDTO toMyPostResDTO(Post post){ return PostResponseDTO.MyPostDTO.builder() + .postId(post.getId()) .nickName(post.getUser().getNickname()) .createdAt(post.getCreatedAt()) .title(post.getTitle()) diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index 47f883e..b78da1d 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -62,6 +62,7 @@ public static class commentSelectRes { @NoArgsConstructor @AllArgsConstructor public static class myCommentRes { + Long postId; String nickName; LocalDateTime createdAt; String content; diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index 5a23da1..970faa9 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -106,6 +106,7 @@ public static class MyInquiryRes{ @NoArgsConstructor @AllArgsConstructor public static class SavedPostCategoryDetailRes{ + Long postId; Long ago; String title; String content; diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 1f08e3c..8f86d86 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -126,6 +126,7 @@ public static class ReviewPostGetResponse{ @NoArgsConstructor @AllArgsConstructor public static class MyPostDTO { + Long postId; String nickName; LocalDateTime createdAt; String title; From d42e6004193bf01aef0753fe098e7d884db55d66 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Thu, 22 Feb 2024 22:55:25 +0900 Subject: [PATCH 214/255] =?UTF-8?q?#164=20Refactor=20:=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20response=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=202=EC=B0=A8#164?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/MyPageConverter.java | 1 + src/main/java/friend/spring/web/dto/MyPageResponseDTO.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index 84052bf..032fe23 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -36,6 +36,7 @@ public static MyPageResponseDTO.SavedPostResDTO toSavedPostResDTO(Post post){ long diffTime = post.getCreatedAt().until(LocalDateTime.now(), ChronoUnit.DAYS); // now보다 이후면 +, 전이면 - return MyPageResponseDTO.SavedPostResDTO.builder() + .postId(post.getId()) .ago(diffTime) .title(post.getTitle()) .content(post.getContent()) diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index 970faa9..32224fc 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -36,6 +36,7 @@ public static class SavedCategoryResDTO{ @NoArgsConstructor @AllArgsConstructor public static class SavedPostResDTO{ + Long postId; Long ago; String title; String content; From bb6d07f61b4f81ba98062402f41989ebcb5851eb Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Thu, 22 Feb 2024 23:44:17 +0900 Subject: [PATCH 215/255] =?UTF-8?q?#155=20Refactor:=20Nginx=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20proxy=5Fread=5Ftimeout=20=EA=B0=92=201=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=20(=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .platform/nginx.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/.platform/nginx.conf b/.platform/nginx.conf index 612092e..67138cd 100644 --- a/.platform/nginx.conf +++ b/.platform/nginx.conf @@ -36,6 +36,7 @@ http { location / { proxy_pass http://springboot; + proxy_read_timeout 3600; # CORS 관련 헤더 추가 add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; From d6c0fcf83c5ecae2a533e6904a3dea25b09afabb Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 23 Feb 2024 00:15:07 +0900 Subject: [PATCH 216/255] =?UTF-8?q?#155=20Refactor:=20Nginx=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20proxy=5Fconnet,=20send=20timeout=20=EA=B0=92=201?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=20(?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .platform/nginx.conf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.platform/nginx.conf b/.platform/nginx.conf index 67138cd..0b196d0 100644 --- a/.platform/nginx.conf +++ b/.platform/nginx.conf @@ -36,7 +36,9 @@ http { location / { proxy_pass http://springboot; - proxy_read_timeout 3600; + proxy_connect_timeout 3600; + proxy_send_timeout 3600; + proxy_read_timeout 3600; # CORS 관련 헤더 추가 add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; From 3e0749788ada1e69517cd49dda753ac81708d4e0 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 23 Feb 2024 07:17:04 +0900 Subject: [PATCH 217/255] =?UTF-8?q?#155=20Refactor:=20Nginx=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20connection=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .platform/nginx.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/.platform/nginx.conf b/.platform/nginx.conf index 0b196d0..4517e13 100644 --- a/.platform/nginx.conf +++ b/.platform/nginx.conf @@ -45,6 +45,7 @@ http { add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; proxy_http_version 1.1; proxy_set_header Connection $connection_upgrade; + proxy_set_header Connection ''; proxy_set_header Upgrade $http_upgrade; proxy_set_header Host $host; From 9d82f1d25dac527783b948a90cdf1de096d07d85 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 23 Feb 2024 07:33:10 +0900 Subject: [PATCH 218/255] =?UTF-8?q?#155=20Refactor:=20Nginx=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20chunked=5Ftransfer=5Fencoding=20off;=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .platform/nginx.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/.platform/nginx.conf b/.platform/nginx.conf index 4517e13..0bdf336 100644 --- a/.platform/nginx.conf +++ b/.platform/nginx.conf @@ -47,6 +47,7 @@ http { proxy_set_header Connection $connection_upgrade; proxy_set_header Connection ''; proxy_set_header Upgrade $http_upgrade; + chunked_transfer_encoding off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; From 1a677095ad89dd2895db0ebf8ac0d3bf36bc4c78 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 23 Feb 2024 07:51:58 +0900 Subject: [PATCH 219/255] =?UTF-8?q?#155=20Refactor:=20nginx.conf=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .platform/{ => nginx}/nginx.conf | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .platform/{ => nginx}/nginx.conf (100%) diff --git a/.platform/nginx.conf b/.platform/nginx/nginx.conf similarity index 100% rename from .platform/nginx.conf rename to .platform/nginx/nginx.conf From fe2850615e914c2a74d2c8e3aa9879cca322fd97 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 23 Feb 2024 08:11:48 +0900 Subject: [PATCH 220/255] =?UTF-8?q?#155=20Refactor:=20nginx=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EC=97=90=EC=84=9C=20timeout=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=EB=A7=8C=20=EB=82=A8=EA=B8=B0=EA=B3=A0=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?(=ED=85=8C=EC=8A=A4=ED=8A=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .platform/nginx/nginx.conf | 2 -- 1 file changed, 2 deletions(-) diff --git a/.platform/nginx/nginx.conf b/.platform/nginx/nginx.conf index 0bdf336..0b196d0 100644 --- a/.platform/nginx/nginx.conf +++ b/.platform/nginx/nginx.conf @@ -45,9 +45,7 @@ http { add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; proxy_http_version 1.1; proxy_set_header Connection $connection_upgrade; - proxy_set_header Connection ''; proxy_set_header Upgrade $http_upgrade; - chunked_transfer_encoding off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; From 9b3717389b5d38e6b481e3936d63acd3b1854412 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Fri, 23 Feb 2024 16:44:57 +0900 Subject: [PATCH 221/255] =?UTF-8?q?#155=20Refactor:=20cors=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EC=97=90=EC=84=9C=20allowedOriginPatterns("*")=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=ED=95=B4=EB=B3=B4=EA=B8=B0=20(=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/config/CorsConfig.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/friend/spring/config/CorsConfig.java b/src/main/java/friend/spring/config/CorsConfig.java index 3ce5a7e..7fc7db3 100644 --- a/src/main/java/friend/spring/config/CorsConfig.java +++ b/src/main/java/friend/spring/config/CorsConfig.java @@ -11,7 +11,6 @@ public class CorsConfig implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") - .allowedOriginPatterns("*") .allowedHeaders("*") .allowedMethods("*") .exposedHeaders("*"); From fa1e4e07d47be9105acb4b4147000fc24925cd50 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 24 Feb 2024 01:33:28 +0900 Subject: [PATCH 222/255] =?UTF-8?q?#155=20Refactor:=20Nginx=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20proxy=20timeout=20=EC=84=A4=EC=A0=95=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .platform/nginx/nginx.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/.platform/nginx/nginx.conf b/.platform/nginx/nginx.conf index 0b196d0..612092e 100644 --- a/.platform/nginx/nginx.conf +++ b/.platform/nginx/nginx.conf @@ -36,9 +36,6 @@ http { location / { proxy_pass http://springboot; - proxy_connect_timeout 3600; - proxy_send_timeout 3600; - proxy_read_timeout 3600; # CORS 관련 헤더 추가 add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; From f0cf0572ceaddc1d5a161ff3b68304c5a1a40f6d Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 24 Feb 2024 02:14:29 +0900 Subject: [PATCH 223/255] =?UTF-8?q?#155=20Refactor:=20cors=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EC=97=90=EC=84=9C=20allowedOriginPatterns("*")=20?= =?UTF-8?q?=EB=8B=A4=EC=8B=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/config/CorsConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/friend/spring/config/CorsConfig.java b/src/main/java/friend/spring/config/CorsConfig.java index 7fc7db3..3ce5a7e 100644 --- a/src/main/java/friend/spring/config/CorsConfig.java +++ b/src/main/java/friend/spring/config/CorsConfig.java @@ -11,6 +11,7 @@ public class CorsConfig implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") + .allowedOriginPatterns("*") .allowedHeaders("*") .allowedMethods("*") .exposedHeaders("*"); From 060f0108d23fa84a3cef40e64a3e053b9f6ea5cc Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 24 Feb 2024 17:18:16 +0900 Subject: [PATCH 224/255] =?UTF-8?q?#155=20Refactor:=20cors=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EC=97=90=EC=84=9C=20.allowedOrigins("*")=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20(=ED=85=8C=EC=8A=A4=ED=8A=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/config/CorsConfig.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/friend/spring/config/CorsConfig.java b/src/main/java/friend/spring/config/CorsConfig.java index 3ce5a7e..756ba5c 100644 --- a/src/main/java/friend/spring/config/CorsConfig.java +++ b/src/main/java/friend/spring/config/CorsConfig.java @@ -10,7 +10,6 @@ public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") - .allowedOrigins("*") .allowedOriginPatterns("*") .allowedHeaders("*") .allowedMethods("*") From 225d5f6860eb49c77e40f9c5c6a1a3373c5a7a7f Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sat, 24 Feb 2024 18:35:17 +0900 Subject: [PATCH 225/255] =?UTF-8?q?#155=20Refactor:=20nginx.conf=EC=97=90?= =?UTF-8?q?=EC=84=9C=20cors=20=EC=84=A4=EC=A0=95=20=EC=A0=9C=EA=B1=B0=20(?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .platform/nginx/nginx.conf | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.platform/nginx/nginx.conf b/.platform/nginx/nginx.conf index 612092e..779e17b 100644 --- a/.platform/nginx/nginx.conf +++ b/.platform/nginx/nginx.conf @@ -36,10 +36,13 @@ http { location / { proxy_pass http://springboot; + proxy_connect_timeout 3600; + proxy_send_timeout 3600; + proxy_read_timeout 3600; # CORS 관련 헤더 추가 - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; +# add_header 'Access-Control-Allow-Origin' '*'; +# add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; +# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; proxy_http_version 1.1; proxy_set_header Connection $connection_upgrade; proxy_set_header Upgrade $http_upgrade; From d42c3a1bc27439b82193e2cfdf6794159ccd2cc6 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 26 Feb 2024 22:03:05 +0900 Subject: [PATCH 226/255] =?UTF-8?q?#155=20Refactor:=20nginx.conf=EC=97=90?= =?UTF-8?q?=EC=84=9C=20cors=20=EC=84=A4=EC=A0=95=20=EC=A0=9C=EA=B1=B0=20(?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .platform/nginx/nginx.conf | 8 ++++--- .../java/friend/spring/config/CorsConfig.java | 24 +++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/.platform/nginx/nginx.conf b/.platform/nginx/nginx.conf index 779e17b..f2fed44 100644 --- a/.platform/nginx/nginx.conf +++ b/.platform/nginx/nginx.conf @@ -40,9 +40,11 @@ http { proxy_send_timeout 3600; proxy_read_timeout 3600; # CORS 관련 헤더 추가 -# add_header 'Access-Control-Allow-Origin' '*'; -# add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; -# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; + add_header 'Access-Control-Allow-Credential' 'true'; + proxy_http_version 1.1; proxy_set_header Connection $connection_upgrade; proxy_set_header Upgrade $http_upgrade; diff --git a/src/main/java/friend/spring/config/CorsConfig.java b/src/main/java/friend/spring/config/CorsConfig.java index 756ba5c..8355d82 100644 --- a/src/main/java/friend/spring/config/CorsConfig.java +++ b/src/main/java/friend/spring/config/CorsConfig.java @@ -4,15 +4,15 @@ import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -@Configuration -public class CorsConfig implements WebMvcConfigurer { - - @Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOriginPatterns("*") - .allowedHeaders("*") - .allowedMethods("*") - .exposedHeaders("*"); - } -} \ No newline at end of file +//@Configuration +//public class CorsConfig implements WebMvcConfigurer { +// +// @Override +// public void addCorsMappings(CorsRegistry registry) { +// registry.addMapping("/**") +// .allowedOriginPatterns("*") +// .allowedHeaders("*") +// .allowedMethods("*") +// .exposedHeaders("*"); +// } +//} \ No newline at end of file From 1b31a9b43a83e926b96444a47484e2a504024937 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 26 Feb 2024 22:04:23 +0900 Subject: [PATCH 227/255] =?UTF-8?q?#155=20Refactor:=20nginx.conf=20cors=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80,=20Access-Control-Allow?= =?UTF-8?q?-Credential=20'true'=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/config/CorsConfig.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/friend/spring/config/CorsConfig.java b/src/main/java/friend/spring/config/CorsConfig.java index 8355d82..98c4df2 100644 --- a/src/main/java/friend/spring/config/CorsConfig.java +++ b/src/main/java/friend/spring/config/CorsConfig.java @@ -1,9 +1,9 @@ -package friend.spring.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - +//package friend.spring.config; +// +//import org.springframework.context.annotation.Configuration; +//import org.springframework.web.servlet.config.annotation.CorsRegistry; +//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +// //@Configuration //public class CorsConfig implements WebMvcConfigurer { // From 6f8baf2403c77edf21adb6e39c4e27279f511264 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 26 Feb 2024 22:20:38 +0900 Subject: [PATCH 228/255] =?UTF-8?q?#155=20Refactor:=20nginx.conf=20cors=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=A0=9C=EA=B1=B0,=20CorsConfig=EC=97=90?= =?UTF-8?q?=20.allowCredentials(true)=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/config/CorsConfig.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/main/java/friend/spring/config/CorsConfig.java b/src/main/java/friend/spring/config/CorsConfig.java index 98c4df2..2b56bf9 100644 --- a/src/main/java/friend/spring/config/CorsConfig.java +++ b/src/main/java/friend/spring/config/CorsConfig.java @@ -1,18 +1,19 @@ -//package friend.spring.config; -// -//import org.springframework.context.annotation.Configuration; -//import org.springframework.web.servlet.config.annotation.CorsRegistry; -//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -// -//@Configuration -//public class CorsConfig implements WebMvcConfigurer { -// -// @Override -// public void addCorsMappings(CorsRegistry registry) { -// registry.addMapping("/**") -// .allowedOriginPatterns("*") -// .allowedHeaders("*") -// .allowedMethods("*") -// .exposedHeaders("*"); -// } -//} \ No newline at end of file +package friend.spring.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class CorsConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOriginPatterns("*") + .allowedHeaders("*") + .allowedMethods("*") + .exposedHeaders("*") + .allowCredentials(true); + } +} \ No newline at end of file From b4cabd301c1082b55bee4bb7ffcd03d1efe0e725 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Mon, 26 Feb 2024 22:28:54 +0900 Subject: [PATCH 229/255] =?UTF-8?q?#155=20Refactor:=20nginx.conf=20cors=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=A0=9C=EA=B1=B0,=20CorsConfig=EC=97=90?= =?UTF-8?q?=20.allowCredentials(true)=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .platform/nginx/nginx.conf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.platform/nginx/nginx.conf b/.platform/nginx/nginx.conf index f2fed44..0316306 100644 --- a/.platform/nginx/nginx.conf +++ b/.platform/nginx/nginx.conf @@ -40,10 +40,10 @@ http { proxy_send_timeout 3600; proxy_read_timeout 3600; # CORS 관련 헤더 추가 - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; - add_header 'Access-Control-Allow-Credential' 'true'; +# add_header 'Access-Control-Allow-Origin' '*'; +# add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; +# add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; +# add_header 'Access-Control-Allow-Credential' 'true'; proxy_http_version 1.1; proxy_set_header Connection $connection_upgrade; From d70de50b69be22a4ac33b256bf3575002307c56c Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Wed, 28 Feb 2024 16:00:07 +0900 Subject: [PATCH 230/255] =?UTF-8?q?#155=20Refactor:=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=BB=A8=EB=B2=A4=EC=85=98=20=EB=A7=9E=EC=B6=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev_deploy.yml | 32 +- src/main/java/friend/spring/Application.java | 16 +- .../friend/spring/apiPayload/ApiResponse.java | 11 +- .../spring/apiPayload/GeneralException.java | 2 +- .../apiPayload/code/status/ErrorStatus.java | 33 +- .../apiPayload/handler/AlarmHandler.java | 4 +- .../friend/spring/aws/s3/AmazonS3Manager.java | 16 +- .../friend/spring/config/EmailConfig.java | 6 +- .../spring/config/RedisRepositoryConfig.java | 2 +- .../java/friend/spring/config/RedisUtil.java | 23 +- .../spring/config/WebSecurityConfig.java | 1 + .../spring/converter/AlarmConverter.java | 4 +- .../spring/converter/Base64Decoder.java | 1 + .../spring/converter/CommentConverter.java | 3 +- .../spring/converter/MyPageConverter.java | 48 +- .../spring/converter/PostConverter.java | 528 +++++++++--------- .../friend/spring/converter/SseConverter.java | 4 +- .../spring/converter/UserConverter.java | 5 +- .../java/friend/spring/domain/Candidate.java | 13 +- .../java/friend/spring/domain/Card_poll.java | 25 +- .../java/friend/spring/domain/Card_vote.java | 12 +- .../java/friend/spring/domain/Category.java | 1 - src/main/java/friend/spring/domain/File.java | 2 +- .../java/friend/spring/domain/Gauge_poll.java | 14 +- .../java/friend/spring/domain/Gauge_vote.java | 9 +- .../friend/spring/domain/General_poll.java | 24 +- .../friend/spring/domain/General_vote.java | 12 +- src/main/java/friend/spring/domain/Point.java | 4 +- src/main/java/friend/spring/domain/Post.java | 39 +- src/main/java/friend/spring/domain/User.java | 18 +- .../repository/General_VoteRepository.java | 2 +- .../spring/repository/PostRepository.java | 6 +- .../spring/repository/UserRepository.java | 2 + .../security/JwtAuthenticationFilter.java | 4 +- .../spring/security/JwtTokenProvider.java | 13 +- .../friend/spring/security/TokenType.java | 3 +- .../spring/service/AlarmServiceImpl.java | 5 +- .../friend/spring/service/CommentService.java | 4 + .../spring/service/CommentServiceImpl.java | 3 +- .../friend/spring/service/EmailService.java | 2 +- .../spring/service/JwtTokenServiceImpl.java | 5 +- .../friend/spring/service/MyPageService.java | 6 +- .../spring/service/MyPageServiceImpl.java | 27 +- .../spring/service/PostQueryService.java | 3 +- .../spring/service/PostQueryServiceImpl.java | 80 +-- .../friend/spring/service/PostService.java | 2 +- .../spring/service/PostServiceImpl.java | 86 +-- .../spring/service/SchedulerService.java | 3 +- .../friend/spring/service/UserService.java | 9 + .../spring/service/UserServiceImpl.java | 3 +- .../friend/spring/service/VoteService.java | 5 +- .../spring/service/VoteServiceImpl.java | 65 +-- .../annotation/ContentTextLimit.java | 4 +- .../validation/annotation/TitleTextLimit.java | 4 +- .../validator/ContentTextLimitValidator.java | 6 +- .../validator/DeadlineLimitValidator.java | 2 +- .../validator/TitleTextLimitValidator.java | 6 +- .../web/controller/AlarmRestController.java | 25 +- .../web/controller/CommentRestController.java | 64 +-- .../web/controller/MyPageRestController.java | 70 +-- .../web/controller/PostRestController.java | 122 ++-- .../spring/web/controller/RootController.java | 1 - .../spring/web/controller/SseController.java | 4 +- .../web/controller/UserRestController.java | 116 ++-- .../web/controller/VoteRestController.java | 31 +- .../spring/web/dto/AlarmResponseDTO.java | 7 +- .../spring/web/dto/CommentResponseDTO.java | 1 + .../spring/web/dto/MyPageRequestDTO.java | 12 +- .../spring/web/dto/MyPageResponseDTO.java | 37 +- .../friend/spring/web/dto/ParentPollDTO.java | 2 +- .../friend/spring/web/dto/ParentPostDTO.java | 2 +- .../friend/spring/web/dto/PostRequestDTO.java | 5 +- .../spring/web/dto/PostResponseDTO.java | 11 +- .../friend/spring/web/dto/SseResponseDTO.java | 2 +- .../friend/spring/web/dto/UserRequestDTO.java | 3 +- .../spring/web/dto/UserResponseDTO.java | 5 +- .../friend/spring/web/dto/VoteRequestDTO.java | 6 +- 77 files changed, 938 insertions(+), 860 deletions(-) diff --git a/.github/workflows/dev_deploy.yml b/.github/workflows/dev_deploy.yml index 21bf8e1..37c9c9d 100644 --- a/.github/workflows/dev_deploy.yml +++ b/.github/workflows/dev_deploy.yml @@ -2,7 +2,7 @@ name: Solution-friend Dev CI/CD on: pull_request: - types: [closed] + types: [ closed ] workflow_dispatch: # (2).수동 실행도 가능하도록 jobs: @@ -41,21 +41,21 @@ jobs: - name: Generate deployment package run: | - mkdir -p deploy - cp build/libs/*.jar deploy/application.jar - cp Procfile deploy/Procfile - cp -r .ebextensions-dev deploy/.ebextensions - cp -r .platform deploy/.platform - cd deploy && zip -r deploy.zip . - + mkdir -p deploy + cp build/libs/*.jar deploy/application.jar + cp Procfile deploy/Procfile + cp -r .ebextensions-dev deploy/.ebextensions + cp -r .platform deploy/.platform + cd deploy && zip -r deploy.zip . + - name: Beanstalk Deploy uses: einaregilsson/beanstalk-deploy@v20 with: - aws_access_key: ${{ secrets.AWS_ACTION_ACCESS_KEY_ID }} - aws_secret_key: ${{ secrets.AWS_ACTION_SECRET_ACCESS_KEY }} - application_name: solution-friend-dev - environment_name: Solution-friend-dev-env - version_label: github-action-${{ steps.current-time.outputs.formattedTime }} - region: ap-northeast-2 - deployment_package: deploy/deploy.zip - wait_for_deployment: false + aws_access_key: ${{ secrets.AWS_ACTION_ACCESS_KEY_ID }} + aws_secret_key: ${{ secrets.AWS_ACTION_SECRET_ACCESS_KEY }} + application_name: solution-friend-dev + environment_name: Solution-friend-dev-env + version_label: github-action-${{ steps.current-time.outputs.formattedTime }} + region: ap-northeast-2 + deployment_package: deploy/deploy.zip + wait_for_deployment: false diff --git a/src/main/java/friend/spring/Application.java b/src/main/java/friend/spring/Application.java index 774f7e9..2c83866 100644 --- a/src/main/java/friend/spring/Application.java +++ b/src/main/java/friend/spring/Application.java @@ -14,14 +14,14 @@ @EnableScheduling public class Application { - @PostConstruct - public void started() { - TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")); - } + @PostConstruct + public void started() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")); + } - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - System.out.println("현재시간 " + LocalDateTime.now()); - } + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + System.out.println("현재시간 " + LocalDateTime.now()); + } } diff --git a/src/main/java/friend/spring/apiPayload/ApiResponse.java b/src/main/java/friend/spring/apiPayload/ApiResponse.java index 6031928..edea1b1 100644 --- a/src/main/java/friend/spring/apiPayload/ApiResponse.java +++ b/src/main/java/friend/spring/apiPayload/ApiResponse.java @@ -21,20 +21,19 @@ public class ApiResponse { private T result; - // 성공한 경우 응답 생성 - public static ApiResponse onSuccess(T result){ - return new ApiResponse<>(true, SuccessStatus._OK.getCode() , SuccessStatus._OK.getMessage(), result); + public static ApiResponse onSuccess(T result) { + return new ApiResponse<>(true, SuccessStatus._OK.getCode(), SuccessStatus._OK.getMessage(), result); } - public static ApiResponse of(BaseCode code, T result){ - return new ApiResponse<>(true, code.getReasonHttpStatus().getCode() , code.getReasonHttpStatus().getMessage(), result); + public static ApiResponse of(BaseCode code, T result) { + return new ApiResponse<>(true, code.getReasonHttpStatus().getCode(), code.getReasonHttpStatus().getMessage(), result); } // 실패한 경우 응답 생성 - public static ApiResponse onFailure(String code, String message, T data){ + public static ApiResponse onFailure(String code, String message, T data) { return new ApiResponse<>(false, code, message, data); } } diff --git a/src/main/java/friend/spring/apiPayload/GeneralException.java b/src/main/java/friend/spring/apiPayload/GeneralException.java index 0b235a9..b67a1e4 100644 --- a/src/main/java/friend/spring/apiPayload/GeneralException.java +++ b/src/main/java/friend/spring/apiPayload/GeneralException.java @@ -15,7 +15,7 @@ public ErrorReasonDTO getErrorReason() { return this.code.getReason(); } - public ErrorReasonDTO getErrorReasonHttpStatus(){ + public ErrorReasonDTO getErrorReasonHttpStatus() { return this.code.getReasonHttpStatus(); } } \ No newline at end of file diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 9ec7b90..a9bd165 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -14,23 +14,23 @@ // 가장 일반적인 응답 _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON5000", "서버 에러, 관리자에게 문의 바랍니다."), - _BAD_REQUEST(HttpStatus.BAD_REQUEST,"COMMON4000","잘못된 요청입니다."), - _UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON4001","인증이 필요합니다."), + _BAD_REQUEST(HttpStatus.BAD_REQUEST, "COMMON4000", "잘못된 요청입니다."), + _UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "COMMON4001", "인증이 필요합니다."), _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON4003", "금지된 요청입니다."), // 멤버 관련 응답 USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USER4001", "회원정보가 존재하지 않습니다."), - USERS_NOT_FOUND_EMAIL(HttpStatus.NOT_FOUND,"USER4010","가입 가능한 이메일입니다."), - USER_EXISTS_EMAIL(HttpStatus.NOT_ACCEPTABLE,"USER4002","이미 존재하는 메일 주소입니다"), + USERS_NOT_FOUND_EMAIL(HttpStatus.NOT_FOUND, "USER4010", "가입 가능한 이메일입니다."), + USER_EXISTS_EMAIL(HttpStatus.NOT_ACCEPTABLE, "USER4002", "이미 존재하는 메일 주소입니다"), UNABLE_TO_SEND_EMAIL(HttpStatus.BAD_REQUEST, "USER4003", "이메일을 발송하지 못했습니다."), ERR_MAKE_CODE(HttpStatus.BAD_REQUEST, "USER4004", "인증 코드 생성에 오류가 있습니다."), INCORRECT_CODE(HttpStatus.UNAUTHORIZED, "USER4005", "인증 코드가 일치하지 않습니다."), EMPTY_JWT(HttpStatus.BAD_REQUEST, "USER4006", "JWT를 입력해주세요."), INVALID_JWT(HttpStatus.UNAUTHORIZED, "USER4007", "유효하지 않은 JWT입니다."), - INVALID_PASSWORD_FORMAT(HttpStatus.NOT_ACCEPTABLE,"USER4077","비밀번호 형식에 맞지 않습니다."), + INVALID_PASSWORD_FORMAT(HttpStatus.NOT_ACCEPTABLE, "USER4077", "비밀번호 형식에 맞지 않습니다."), PASSWORD_INCORRECT(HttpStatus.NOT_FOUND, "USER4008", "비밀번호가 틀렸습니다."), PASSWORD_CHECK_INCORRECT(HttpStatus.NOT_FOUND, "USER4009", "확인 비밀번호가 일치하지 않습니다."), - RTK_INCORREXT(HttpStatus.UNAUTHORIZED,"USER4100","RefreshToken값을 확인해주세요."), + RTK_INCORREXT(HttpStatus.UNAUTHORIZED, "USER4100", "RefreshToken값을 확인해주세요."), NOT_ADMIN(HttpStatus.BAD_REQUEST, "USER4101", "관리자가 아닙니다."), // Auth 관련 @@ -50,17 +50,17 @@ POST_SCRAP_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4004", "글에 대한 스크랩 데이터를 찾을 수 없습니다."), POST_GENERAL_POLL_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4005", "글에 대한 일반 투표 데이터를 찾을 수 없습니다."), POST_CARD_POLL_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4006", "글에 대한 카드 투표 데이터를 찾을 수 없습니다."), - TITLE_TEXT_LIMIT(HttpStatus.BAD_REQUEST,"POST4007","최소 5자 이상, 30자 미만 입력해 주세요"), - CONTENT_TEXT_LIMIT(HttpStatus.BAD_REQUEST,"POST4008","최소 5자 이상, 1000자 미만 입력해 주세요"), - CANDIDATE_TEXT_LIMIT(HttpStatus.BAD_REQUEST,"POST4009","최소 1자 이상, 30자 미만 입력해 주세요"), - DEADLINE_LIMIT(HttpStatus.BAD_REQUEST,"POST4010","최소 1분~최대30일로 입력해 주세요"), - CANDIDATE_NOT_FOUND(HttpStatus.NOT_FOUND,"POST4011","후보를 찾을 수 없습니다"), - TOO_MUCH_FIXED(HttpStatus.NOT_FOUND,"POST4012","이미 2회 이상 수정 했습니다"), - NOT_ENOUGH_POINT(HttpStatus.BAD_REQUEST,"POST4013","해당 유저의 포인트가 부족 합니다"), + TITLE_TEXT_LIMIT(HttpStatus.BAD_REQUEST, "POST4007", "최소 5자 이상, 30자 미만 입력해 주세요"), + CONTENT_TEXT_LIMIT(HttpStatus.BAD_REQUEST, "POST4008", "최소 5자 이상, 1000자 미만 입력해 주세요"), + CANDIDATE_TEXT_LIMIT(HttpStatus.BAD_REQUEST, "POST4009", "최소 1자 이상, 30자 미만 입력해 주세요"), + DEADLINE_LIMIT(HttpStatus.BAD_REQUEST, "POST4010", "최소 1분~최대30일로 입력해 주세요"), + CANDIDATE_NOT_FOUND(HttpStatus.NOT_FOUND, "POST4011", "후보를 찾을 수 없습니다"), + TOO_MUCH_FIXED(HttpStatus.NOT_FOUND, "POST4012", "이미 2회 이상 수정 했습니다"), + NOT_ENOUGH_POINT(HttpStatus.BAD_REQUEST, "POST4013", "해당 유저의 포인트가 부족 합니다"), POST_LIKE_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4014", "글에 대한 좋아요 데이터가 이미 존재합니다."), POST_SCRAP_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4015", "글에 대한 스크랩 데이터가 이미 존재합니다."), - DEADLINE_OVER(HttpStatus.BAD_REQUEST,"POST4016","투표 마감 시간이 지났습니다"), - ALREADY_VOTE(HttpStatus.BAD_REQUEST,"POST4017","이미 투표 하셨습니다."), + DEADLINE_OVER(HttpStatus.BAD_REQUEST, "POST4016", "투표 마감 시간이 지났습니다"), + ALREADY_VOTE(HttpStatus.BAD_REQUEST, "POST4017", "이미 투표 하셨습니다."), // USER_VOTE(HttpStatus.BAD_REQUEST,"POST4017","작성자는 투표가 불가능 합니다 하셨습니다."), // 댓글 관련 응답 @@ -77,8 +77,7 @@ // 공지사항 관련 응답 - NOTICE_NOT_FOUND(HttpStatus.NOT_FOUND, "NOTICE4001", "공지사항이 없습니다.") - ; + NOTICE_NOT_FOUND(HttpStatus.NOT_FOUND, "NOTICE4001", "공지사항이 없습니다."); private final HttpStatus httpStatus; private final String code; diff --git a/src/main/java/friend/spring/apiPayload/handler/AlarmHandler.java b/src/main/java/friend/spring/apiPayload/handler/AlarmHandler.java index ec9f5dc..b0162b5 100644 --- a/src/main/java/friend/spring/apiPayload/handler/AlarmHandler.java +++ b/src/main/java/friend/spring/apiPayload/handler/AlarmHandler.java @@ -4,5 +4,7 @@ import friend.spring.apiPayload.code.BaseErrorCode; public class AlarmHandler extends GeneralException { - public AlarmHandler(BaseErrorCode errorCode){super(errorCode);} + public AlarmHandler(BaseErrorCode errorCode) { + super(errorCode); + } } diff --git a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java index 5046e3c..89bac6c 100644 --- a/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java +++ b/src/main/java/friend/spring/aws/s3/AmazonS3Manager.java @@ -18,7 +18,7 @@ @Slf4j @Component @RequiredArgsConstructor -public class AmazonS3Manager{ +public class AmazonS3Manager { private final AmazonS3 amazonS3; @@ -28,19 +28,19 @@ public class AmazonS3Manager{ private final UuidRepository uuidRepository; - public String uploadFile(String keyName, MultipartFile file){ + public String uploadFile(String keyName, MultipartFile file) { ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentLength(file.getSize()); try { PutObjectRequest putObjectRequest = PutObjectRequest.builder() - .bucket(amazonConfig.getBucket()) - .key(keyName) - .contentType(file.getContentType()) - .contentDisposition("inline") - .build(); + .bucket(amazonConfig.getBucket()) + .key(keyName) + .contentType(file.getContentType()) + .contentDisposition("inline") + .build(); s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(file.getInputStream(), file.getSize())); - }catch (IOException e){ + } catch (IOException e) { log.error("error at AmazonS3Manager uploadFile : {}", (Object) e.getStackTrace()); } diff --git a/src/main/java/friend/spring/config/EmailConfig.java b/src/main/java/friend/spring/config/EmailConfig.java index 6aa4ff2..acb52d0 100644 --- a/src/main/java/friend/spring/config/EmailConfig.java +++ b/src/main/java/friend/spring/config/EmailConfig.java @@ -43,14 +43,14 @@ public JavaMailSender javaMailService() { javaMailSender.setDefaultEncoding("UTF-8"); return javaMailSender; } - private Properties getMailProperties() - { + + private Properties getMailProperties() { Properties pt = new Properties(); pt.put("mail.smtp.socketFactory.port", socketPort); pt.put("mail.smtp.auth", auth); pt.put("mail.smtp.starttls.enable", starttls); pt.put("mail.smtp.starttls.required", startlls_required); - pt.put("mail.smtp.socketFactory.fallback",fallback); + pt.put("mail.smtp.socketFactory.fallback", fallback); //pt.put("mail.smtp.socketFactory.class", "javax.net.tls.SSLSocketFactory"); return pt; } diff --git a/src/main/java/friend/spring/config/RedisRepositoryConfig.java b/src/main/java/friend/spring/config/RedisRepositoryConfig.java index 6cb65af..e4380d0 100644 --- a/src/main/java/friend/spring/config/RedisRepositoryConfig.java +++ b/src/main/java/friend/spring/config/RedisRepositoryConfig.java @@ -25,7 +25,7 @@ public class RedisRepositoryConfig { // RedisConnectionFactory 인터페이스를 통해 LettuceConnectionFactory를 생성하여 반환한다. // RedisProperties로 yaml에 저장한 host, post를 가지고 와서 연결한다. @Bean - public RedisConnectionFactory redisConnectionFactory(){ + public RedisConnectionFactory redisConnectionFactory() { return new LettuceConnectionFactory(host, port); } diff --git a/src/main/java/friend/spring/config/RedisUtil.java b/src/main/java/friend/spring/config/RedisUtil.java index 1925cf3..046d242 100644 --- a/src/main/java/friend/spring/config/RedisUtil.java +++ b/src/main/java/friend/spring/config/RedisUtil.java @@ -13,20 +13,23 @@ public class RedisUtil { private final StringRedisTemplate redisTemplate;//Redis에 접근하기 위한 Spring의 Redis 템플릿 클래스 - public String getData(String key){//지정된 키(key)에 해당하는 데이터를 Redis에서 가져오는 메서드 - ValueOperations valueOperations=redisTemplate.opsForValue(); + public String getData(String key) {//지정된 키(key)에 해당하는 데이터를 Redis에서 가져오는 메서드 + ValueOperations valueOperations = redisTemplate.opsForValue(); return valueOperations.get(key); } - public void setData(String key,String value){//지정된 키(key)에 값을 저장하는 메서드 - ValueOperations valueOperations=redisTemplate.opsForValue(); - valueOperations.set(key,value); + + public void setData(String key, String value) {//지정된 키(key)에 값을 저장하는 메서드 + ValueOperations valueOperations = redisTemplate.opsForValue(); + valueOperations.set(key, value); } - public void setDataExpire(String key,String value,long duration){//지정된 키(key)에 값을 저장하고, 지정된 시간(duration) 후에 데이터가 만료되도록 설정하는 메서드 - ValueOperations valueOperations=redisTemplate.opsForValue(); - Duration expireDuration=Duration.ofSeconds(duration); - valueOperations.set(key,value,expireDuration); + + public void setDataExpire(String key, String value, long duration) {//지정된 키(key)에 값을 저장하고, 지정된 시간(duration) 후에 데이터가 만료되도록 설정하는 메서드 + ValueOperations valueOperations = redisTemplate.opsForValue(); + Duration expireDuration = Duration.ofSeconds(duration); + valueOperations.set(key, value, expireDuration); } - public void deleteData(String key){//지정된 키(key)에 해당하는 데이터를 Redis에서 삭제하는 메서드 + + public void deleteData(String key) {//지정된 키(key)에 해당하는 데이터를 Redis에서 삭제하는 메서드 redisTemplate.delete(key); } } \ No newline at end of file diff --git a/src/main/java/friend/spring/config/WebSecurityConfig.java b/src/main/java/friend/spring/config/WebSecurityConfig.java index b40aac0..7b69c45 100644 --- a/src/main/java/friend/spring/config/WebSecurityConfig.java +++ b/src/main/java/friend/spring/config/WebSecurityConfig.java @@ -28,6 +28,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { diff --git a/src/main/java/friend/spring/converter/AlarmConverter.java b/src/main/java/friend/spring/converter/AlarmConverter.java index 8a23f9c..c5e5ed7 100644 --- a/src/main/java/friend/spring/converter/AlarmConverter.java +++ b/src/main/java/friend/spring/converter/AlarmConverter.java @@ -14,7 +14,7 @@ public class AlarmConverter { //알림 - public static AlarmResponseDTO.AlarmResDTO toAlarmResDTO(Alarm alarm){ + public static AlarmResponseDTO.AlarmResDTO toAlarmResDTO(Alarm alarm) { Long commentId = null; String commentContent = null; String userNickname = null; @@ -42,7 +42,7 @@ public static AlarmResponseDTO.AlarmResDTO toAlarmResDTO(Alarm alarm){ .build(); } - public static AlarmResponseDTO.AlarmListResDTO toAlarmListResDTO(Page alarmList){ + public static AlarmResponseDTO.AlarmListResDTO toAlarmListResDTO(Page alarmList) { List alarmResDTOList = alarmList.stream() .map(AlarmConverter::toAlarmResDTO).collect(Collectors.toList()); return AlarmResponseDTO.AlarmListResDTO.builder() diff --git a/src/main/java/friend/spring/converter/Base64Decoder.java b/src/main/java/friend/spring/converter/Base64Decoder.java index d181c43..7d83801 100644 --- a/src/main/java/friend/spring/converter/Base64Decoder.java +++ b/src/main/java/friend/spring/converter/Base64Decoder.java @@ -1,6 +1,7 @@ package friend.spring.converter; import org.springframework.web.multipart.MultipartFile; + import java.io.*; import java.util.Base64; diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index 59ccfd0..97b6051 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -104,7 +104,8 @@ public static CommentResponseDTO.commentSelectRes toCommentSelectRes(Comment_cho .point(comment_choice.getPoint()) .build(); } - public static CommentResponseDTO.myCommentRes toMyCommentResDTO(Comment comment){ + + public static CommentResponseDTO.myCommentRes toMyCommentResDTO(Comment comment) { return CommentResponseDTO.myCommentRes.builder() .postId(comment.getPost().getId()) .nickName(comment.getUser().getNickname()) diff --git a/src/main/java/friend/spring/converter/MyPageConverter.java b/src/main/java/friend/spring/converter/MyPageConverter.java index 032fe23..383591e 100644 --- a/src/main/java/friend/spring/converter/MyPageConverter.java +++ b/src/main/java/friend/spring/converter/MyPageConverter.java @@ -17,22 +17,23 @@ import static java.util.Calendar.HOUR; import static java.util.Calendar.SECOND; import static java.util.Calendar.MINUTE; + public class MyPageConverter { - public static MyPageResponseDTO.CategoryResDTO toCategoryResDTO(Category category){ + public static MyPageResponseDTO.CategoryResDTO toCategoryResDTO(Category category) { return MyPageResponseDTO.CategoryResDTO.builder() .categoryId(category.getId()) .category(category.getName()) .build(); } - public static MyPageResponseDTO.SavedCategoryResDTO toSavedCategoryResDTO(List categoryList){ + public static MyPageResponseDTO.SavedCategoryResDTO toSavedCategoryResDTO(List categoryList) { List categoryNameList = categoryList.stream() .map(MyPageConverter::toCategoryResDTO).collect(Collectors.toList()); return MyPageResponseDTO.SavedCategoryResDTO.builder() .postCategoryList(categoryNameList).build(); } - public static MyPageResponseDTO.SavedPostResDTO toSavedPostResDTO(Post post){ + public static MyPageResponseDTO.SavedPostResDTO toSavedPostResDTO(Post post) { long diffTime = post.getCreatedAt().until(LocalDateTime.now(), ChronoUnit.DAYS); // now보다 이후면 +, 전이면 - return MyPageResponseDTO.SavedPostResDTO.builder() @@ -44,15 +45,15 @@ public static MyPageResponseDTO.SavedPostResDTO toSavedPostResDTO(Post post){ .comment(post.getCommentList().size()).build(); } - public static MyPageResponseDTO.SavedAllPostResDTO toSavedAllPostResDTO(Page postList){ + public static MyPageResponseDTO.SavedAllPostResDTO toSavedAllPostResDTO(Page postList) { List savedAllPostList = postList.stream().map(MyPageConverter::toSavedPostResDTO).collect(Collectors.toList()); return MyPageResponseDTO.SavedAllPostResDTO.builder() .postList(savedAllPostList).build(); } - public static MyPageResponseDTO.MyProfileResDTO toMyProfileResDTO(User user){ + public static MyPageResponseDTO.MyProfileResDTO toMyProfileResDTO(User user) { String userPhoto = null; - if(user.getFile() != null){ + if (user.getFile() != null) { userPhoto = user.getFile().getUrl(); } return MyPageResponseDTO.MyProfileResDTO.builder() @@ -63,42 +64,43 @@ public static MyPageResponseDTO.MyProfileResDTO toMyProfileResDTO(User user){ .build(); } - public static User toUserName(MyPageRequestDTO.ProfileEditNameReq profileEditNameReq){ + public static User toUserName(MyPageRequestDTO.ProfileEditNameReq profileEditNameReq) { return User.builder() .nickname(profileEditNameReq.getNickName()) .build(); } - public static MyPageResponseDTO.ProfileEditNameRes toProfileEditNameResDTO(User user){ + + public static MyPageResponseDTO.ProfileEditNameRes toProfileEditNameResDTO(User user) { return MyPageResponseDTO.ProfileEditNameRes.builder() .nickName(user.getNickname()) .build(); } - public static MyPageResponseDTO.ProfileEditEmailRes toProfileEditEmailResDTO(User user){ + public static MyPageResponseDTO.ProfileEditEmailRes toProfileEditEmailResDTO(User user) { return MyPageResponseDTO.ProfileEditEmailRes.builder() .changeEmail(user.getEmail()) .build(); } - public static User toUserEmail(MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq){ + public static User toUserEmail(MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq) { return User.builder() .email(profileEditEmailReq.getChangeEmail()) .build(); } - public static MyPageResponseDTO.ProfileEditPhoneRes toProfileEditPhoneResDTO(User user){ + public static MyPageResponseDTO.ProfileEditPhoneRes toProfileEditPhoneResDTO(User user) { return MyPageResponseDTO.ProfileEditPhoneRes.builder() .phone(user.getPhone()) .build(); } - public static MyPageResponseDTO.ProfileEditPasswordRes toProfileEditPasswordResDTO(User user){ + public static MyPageResponseDTO.ProfileEditPasswordRes toProfileEditPasswordResDTO(User user) { return MyPageResponseDTO.ProfileEditPasswordRes.builder() .changePassword(user.getPassword()) .build(); } - public static Inquiry toInquiry(MyPageRequestDTO.MyInquiryReq myInquiryReq, User user){ + public static Inquiry toInquiry(MyPageRequestDTO.MyInquiryReq myInquiryReq, User user) { return Inquiry.builder() .category(myInquiryReq.getInquiryCategory()) .content(myInquiryReq.getContent()) @@ -106,13 +108,13 @@ public static Inquiry toInquiry(MyPageRequestDTO.MyInquiryReq myInquiryReq, User .build(); } - public static MyPageResponseDTO.MyInquiryRes toMyInquiryRes(Inquiry inquiry){ + public static MyPageResponseDTO.MyInquiryRes toMyInquiryRes(Inquiry inquiry) { return MyPageResponseDTO.MyInquiryRes.builder() .inquiry_id(inquiry.getId()) .build(); } - public static MyPageResponseDTO.SavedPostCategoryDetailRes toSavedPostCategoryDetailRes(Post post){ + public static MyPageResponseDTO.SavedPostCategoryDetailRes toSavedPostCategoryDetailRes(Post post) { long diffTime = post.getCreatedAt().until(LocalDateTime.now(), ChronoUnit.DAYS); // now보다 이후면 +, 전이면 - return MyPageResponseDTO.SavedPostCategoryDetailRes.builder() @@ -125,7 +127,7 @@ public static MyPageResponseDTO.SavedPostCategoryDetailRes toSavedPostCategoryDe .build(); } - public static MyPageResponseDTO.SavedPostCategoryDetailListRes toSavedPostCategoryDetailListRes(Page postList, Category category){ + public static MyPageResponseDTO.SavedPostCategoryDetailListRes toSavedPostCategoryDetailListRes(Page postList, Category category) { List postCategoryDetailResList = postList.stream().map(MyPageConverter::toSavedPostCategoryDetailRes).collect(Collectors.toList()); return MyPageResponseDTO.SavedPostCategoryDetailListRes.builder() .name(category.getName()) @@ -133,11 +135,11 @@ public static MyPageResponseDTO.SavedPostCategoryDetailListRes toSavedPostCatego .build(); } - public static MyPageResponseDTO.NoticeRes toNoticeRes(Notice notice){ + public static MyPageResponseDTO.NoticeRes toNoticeRes(Notice notice) { long diffTime = notice.getCreatedAt().until(LocalDateTime.now(), ChronoUnit.DAYS); // now보다 이후면 +, 전이면 - String adminImage = null; - if (notice.getUser().getFile() != null){ + if (notice.getUser().getFile() != null) { adminImage = notice.getUser().getFile().getUrl(); } return MyPageResponseDTO.NoticeRes.builder() @@ -148,16 +150,16 @@ public static MyPageResponseDTO.NoticeRes toNoticeRes(Notice notice){ .build(); } - public static MyPageResponseDTO.NoticeListRes toNoticeListRes(Page noticeList){ + public static MyPageResponseDTO.NoticeListRes toNoticeListRes(Page noticeList) { List noticeResList = noticeList.stream().map(MyPageConverter::toNoticeRes).collect(Collectors.toList()); return MyPageResponseDTO.NoticeListRes.builder() .noticeList(noticeResList) .build(); } - public static MyPageResponseDTO.NoticeDetailRes toNoticeDetailRes(Notice notice){ + public static MyPageResponseDTO.NoticeDetailRes toNoticeDetailRes(Notice notice) { String adminImage = null; - if (notice.getUser().getFile() != null){ + if (notice.getUser().getFile() != null) { adminImage = notice.getUser().getFile().getUrl(); } return MyPageResponseDTO.NoticeDetailRes.builder() @@ -169,13 +171,13 @@ public static MyPageResponseDTO.NoticeDetailRes toNoticeDetailRes(Notice notice) .build(); } - public static MyPageResponseDTO.TermRes toTermRes(Term term){ + public static MyPageResponseDTO.TermRes toTermRes(Term term) { return MyPageResponseDTO.TermRes.builder() .content(term.getTerm()) .build(); } - public static MyPageResponseDTO.PrivacyRes toPrivacyRes(Term term){ + public static MyPageResponseDTO.PrivacyRes toPrivacyRes(Term term) { return MyPageResponseDTO.PrivacyRes.builder() .content(term.getPrivacy()) .build(); diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 28ef3dc..3a2f7a9 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -1,4 +1,5 @@ package friend.spring.converter; + import friend.spring.domain.*; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; @@ -12,6 +13,7 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; + import friend.spring.domain.Post; import friend.spring.domain.User; @@ -28,6 +30,7 @@ public class PostConverter { private static PostQueryService postQueryService; + public static PostResponseDTO.AddPostResultDTO toAddPostResultDTO(Post post) { return PostResponseDTO.AddPostResultDTO.builder() .postId(post.getId()) @@ -46,20 +49,20 @@ public static PollOptionDTO.PollOptionRes toPollOptionResDTO(Candidate candidate .optionImgUrl(optionImgUrl).build(); } - public static ParentPostDTO toParentPostDTO(Post parentPost){ - ParentPollDTO parentPollDTO=null; - Integer parentLikes =parentPost.getPostLikeList().size(); - Integer parentComments= parentPost.getCommentList().size(); - File userFile=null; - String userImg=null; - Optional userFileOptional=Optional.ofNullable(parentPost.getUser().getFile()); + public static ParentPostDTO toParentPostDTO(Post parentPost) { + ParentPollDTO parentPollDTO = null; + Integer parentLikes = parentPost.getPostLikeList().size(); + Integer parentComments = parentPost.getCommentList().size(); + File userFile = null; + String userImg = null; + Optional userFileOptional = Optional.ofNullable(parentPost.getUser().getFile()); - if(userFileOptional.isPresent()){ + if (userFileOptional.isPresent()) { userFile = userFileOptional.get(); - userImg=userFile.getUrl(); + userImg = userFile.getUrl(); } - if(parentPost.getVoteType()==PostVoteType.GAUGE) { + if (parentPost.getVoteType() == PostVoteType.GAUGE) { return ParentPostDTO.builder() .nickname(parentPost.getUser().getNickname()) .userImg(userImg) @@ -71,7 +74,7 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ .build(); } - if(parentPost.getVoteType()==PostVoteType.GENERAL) { + if (parentPost.getVoteType() == PostVoteType.GENERAL) { List pollOptionDTOList = parentPost.getGeneralPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); @@ -100,16 +103,16 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ .max(Comparator.comparingInt(ParentPollDTO::getRate)); // 1등 후보의 정보를 ParentPollDTO 객체로 반환 - if(highestSelectionCandidate.isPresent()) { + if (highestSelectionCandidate.isPresent()) { parentPollDTO = highestSelectionCandidate.get(); // 1등 후보 이름, 사진 반환 - Long id=parentPollDTO.getCandidateId(); + Long id = parentPollDTO.getCandidateId(); //1등이 있는 경우만 포함. Optional name = parentPost.getGeneralPoll().getCandidateList().stream() .filter(candidate -> candidate.getId().equals(id)) .map(Candidate::getName) .findFirst(); - String candidateName=name.get(); + String candidateName = name.get(); String candidateImage = parentPollDTO.getCandidateImage(); @@ -131,79 +134,79 @@ public static ParentPostDTO toParentPostDTO(Post parentPost){ .build(); } - List pollOptionDTOList = parentPost.getCardPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); + List pollOptionDTOList = parentPost.getCardPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - // 총 투표수 계산 - long totalVotes = parentPost.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); + // 총 투표수 계산 + long totalVotes = parentPost.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = parentPost.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = parentPost.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - // 선택률 -> ParentPollDTO 객체 리스트로 변환 - List candidateInfos = candidateSelectionCounts.entrySet().stream() - .map(entry -> ParentPollDTO.builder() - .candidateId(entry.getKey()) - .rate((int) ((double) entry.getValue() / totalVotes * 100)) - .selection(entry.getValue()) - .build()) - .collect(Collectors.toList()); + // 선택률 -> ParentPollDTO 객체 리스트로 변환 + List candidateInfos = candidateSelectionCounts.entrySet().stream() + .map(entry -> ParentPollDTO.builder() + .candidateId(entry.getKey()) + .rate((int) ((double) entry.getValue() / totalVotes * 100)) + .selection(entry.getValue()) + .build()) + .collect(Collectors.toList()); - // 선택률이 가장 높은 후보 찾기 - Optional highestSelectionCandidate = candidateInfos.stream() - .max(Comparator.comparingInt(ParentPollDTO::getRate)); - //1등이 있는 경우만 - if(highestSelectionCandidate.isPresent()) { - // 1등 후보의 정보를 ParentPollDTO 객체로 반환 - parentPollDTO = highestSelectionCandidate.get(); + // 선택률이 가장 높은 후보 찾기 + Optional highestSelectionCandidate = candidateInfos.stream() + .max(Comparator.comparingInt(ParentPollDTO::getRate)); + //1등이 있는 경우만 + if (highestSelectionCandidate.isPresent()) { + // 1등 후보의 정보를 ParentPollDTO 객체로 반환 + parentPollDTO = highestSelectionCandidate.get(); - // 1등 후보 이름, 사진 반환 - Long id=parentPollDTO.getCandidateId(); - Optional name = parentPost.getCardPoll().getCandidateList().stream() - .filter(candidate -> candidate.getId().equals(id)) - .map(Candidate::getName) - .findFirst(); - String candidateName=name.get(); + // 1등 후보 이름, 사진 반환 + Long id = parentPollDTO.getCandidateId(); + Optional name = parentPost.getCardPoll().getCandidateList().stream() + .filter(candidate -> candidate.getId().equals(id)) + .map(Candidate::getName) + .findFirst(); + String candidateName = name.get(); - String candidateImage=parentPollDTO.getCandidateImage(); - parentPollDTO.setCandidateName(candidateName); - parentPollDTO.setCandidateImage(candidateImage); - } + String candidateImage = parentPollDTO.getCandidateImage(); + parentPollDTO.setCandidateName(candidateName); + parentPollDTO.setCandidateImage(candidateImage); + } - return ParentPostDTO.builder() - .nickname(parentPost.getUser().getNickname()) - .userImg(userImg) - .title(parentPost.getTitle()) - .content(parentPost.getContent()) - .pollOption(pollOptionDTOList) - .pollContent(parentPollDTO) - .like(parentLikes) - .comment(parentComments) - .build(); + return ParentPostDTO.builder() + .nickname(parentPost.getUser().getNickname()) + .userImg(userImg) + .title(parentPost.getTitle()) + .content(parentPost.getContent()) + .pollOption(pollOptionDTOList) + .pollContent(parentPollDTO) + .like(parentLikes) + .comment(parentComments) + .build(); } public static Post toPost(PostRequestDTO.AddPostDTO request) { - PostType postType=null; - PostVoteType postVoteType=null; + PostType postType = null; + PostVoteType postVoteType = null; - switch (request.getPostType()){ + switch (request.getPostType()) { case 1: - postType=PostType.VOTE; + postType = PostType.VOTE; break; case 2: - postType=PostType.REVIEW; + postType = PostType.REVIEW; break; default: break; } - if(postType== VOTE) { + if (postType == VOTE) { switch (request.getPostVoteType()) { case 1: postVoteType = PostVoteType.GENERAL; @@ -220,7 +223,6 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { } - return Post.builder() .title(request.getTitle()) .content(request.getContent()) @@ -233,37 +235,36 @@ public static Post toPost(PostRequestDTO.AddPostDTO request) { } - //글 상세 보기 - public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, Boolean engage,Long userId, Post parentPost){ + public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, Boolean engage, Long userId, Post parentPost) { Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); - Boolean myPost=false; - List userChoiceList=null; - List topCandidateList=null; - List userVotePercent=null; - List topCandidatePercent=null; - List allCandidatePercent=null; - List userVoteResult=null; - List topVoteResult=null; - Integer userGauge=null; - Integer totalGauge=null; - Boolean isVote=false; - Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); - Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); - if(post.getUser().getId().equals(userId)){ - myPost=true; + Boolean myPost = false; + List userChoiceList = null; + List topCandidateList = null; + List userVotePercent = null; + List topCandidatePercent = null; + List allCandidatePercent = null; + List userVoteResult = null; + List topVoteResult = null; + Integer userGauge = null; + Integer totalGauge = null; + Boolean isVote = false; + Boolean isLike = !post.getPostLikeList().stream().filter(like -> like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + Boolean isComment = !post.getCommentList().stream().filter(like -> like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + if (post.getUser().getId().equals(userId)) { + myPost = true; } - File userFile=null; - String userImg=null; - Optional userFileOptional=Optional.ofNullable(post.getUser().getFile()); + File userFile = null; + String userImg = null; + Optional userFileOptional = Optional.ofNullable(post.getUser().getFile()); - if(userFileOptional.isPresent()){ + if (userFileOptional.isPresent()) { userFile = userFileOptional.get(); - userImg=userFile.getUrl(); + userImg = userFile.getUrl(); } - if(post.getPostType()==REVIEW){ + if (post.getPostType() == REVIEW) { return PostResponseDTO.PostDetailResponse.builder() .postType(REVIEW) .postVoteType(null) @@ -282,25 +283,25 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .myPost(myPost) .build(); } - if(post.getVoteType()==PostVoteType.GAUGE){ + if (post.getVoteType() == PostVoteType.GAUGE) { //나노초 단위로 마감 여부 확인 LocalDateTime now = LocalDateTime.now(); long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGaugePoll().getDeadline()); Boolean voteOnGoing = nanosUntilDeadline > 0; //투표에 참여 했을 경우 - if(engage){ - OptionaluserGaugeVoteOptional=post.getGaugePoll().getGaugeVoteList().stream() + if (engage) { + Optional userGaugeVoteOptional = post.getGaugePoll().getGaugeVoteList().stream() .filter(gaugeVote -> gaugeVote.getUser().getId().equals(userId)) .findFirst(); - if(userGaugeVoteOptional.isPresent()){ - userGauge=userGaugeVoteOptional.get().getValue(); + if (userGaugeVoteOptional.isPresent()) { + userGauge = userGaugeVoteOptional.get().getValue(); } - isVote=true; - totalGauge=post.getGaugePoll().getGauge(); + isVote = true; + totalGauge = post.getGaugePoll().getGauge(); } - if(post.getGaugePoll().getDeadline().isBefore(LocalDateTime.now())||myPost){ - totalGauge=post.getGaugePoll().getGauge(); + if (post.getGaugePoll().getDeadline().isBefore(LocalDateTime.now()) || myPost) { + totalGauge = post.getGaugePoll().getGauge(); } return PostResponseDTO.PostDetailResponse.builder() .postType(VOTE) @@ -326,119 +327,119 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .myPost(myPost) .build(); } - if(post.getVoteType()==PostVoteType.GENERAL){ + if (post.getVoteType() == PostVoteType.GENERAL) { //나노초 단위로 마감 여부 확인 LocalDateTime now = LocalDateTime.now(); long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGeneralPoll().getDeadline()); Boolean voteOnGoing = nanosUntilDeadline > 0; //투표 후보 리스트 - List pollOptionDTOList=post.getGeneralPoll().getCandidateList().stream() + List pollOptionDTOList = post.getGeneralPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - if(post.getGeneralPoll().getDeadline().isAfter(LocalDateTime.now())){ - if(engage) { - //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(generalVote -> generalVote.getUser().getId().equals(userId)) - .flatMap(generalVote -> generalVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); + if (post.getGeneralPoll().getDeadline().isAfter(LocalDateTime.now())) { + if (engage) { + //투표한 후보에 대한 정보 + Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(generalVote -> generalVote.getUser().getId().equals(userId)) + .flatMap(generalVote -> generalVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); - // 총 투표수 계산 - // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(vote -> vote.getUser().getId().equals(userId)) - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.toList()); + // 총 투표수 계산 + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); - // 총 투표수 계산 - long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); + // 총 투표수 계산 + long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - // 사용자가 선택한 후보의 선택률 계산 - userVotePercent = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); - // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) - userVoteResult = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return String.format("%d/%d", selectionCount, totalVotes); - }) - .collect(Collectors.toList()); - isVote=true; - // 투표수가 가장 많은 후보의 선택률 계산 - OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() - .mapToDouble(aLong -> (double) aLong.getValue() / totalVotes) - .max(); + // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) + userVoteResult = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + isVote = true; + // 투표수가 가장 많은 후보의 선택률 계산 + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() + .mapToDouble(aLong -> (double) aLong.getValue() / totalVotes) + .max(); - // 선택률이 가장 높은 후보의 ID들 찾기 - List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 - topCandidateList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); + // 선택률이 가장 높은 후보의 ID들 찾기 + List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() + .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + topCandidateList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); - topCandidatePercent = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); + topCandidatePercent = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); - topVoteResult = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return String.format("%d/%d", selectionCount, totalVotes); - }) - .collect(Collectors.toList()); - } - return PostResponseDTO.PostDetailResponse.builder() - .OnGoing(voteOnGoing) - .isVoted(isVote) - .postType(VOTE) - .postVoteType(PostVoteType.GENERAL) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .createdAt(post.getCreatedAt()) - .title(post.getTitle()) - .content(post.getContent()) - .file(FileConverter.toFileDTO(post.getFileList())) - .pollTitle(post.getGeneralPoll().getPollTitle()) - .pollOption(pollOptionDTOList) - .topCandidate(topCandidateList) - .userVote(userChoiceList) - .userVotePercent(userVotePercent) - .userVoteResult(userVoteResult) - .topVoteResult(topVoteResult) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .point(post.getPoint()) - .deadline(post.getGeneralPoll().getDeadline()) - .view(post.getView()) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .myPost(myPost) - .build(); + topVoteResult = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + } + return PostResponseDTO.PostDetailResponse.builder() + .OnGoing(voteOnGoing) + .isVoted(isVote) + .postType(VOTE) + .postVoteType(PostVoteType.GENERAL) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .createdAt(post.getCreatedAt()) + .title(post.getTitle()) + .content(post.getContent()) + .file(FileConverter.toFileDTO(post.getFileList())) + .pollTitle(post.getGeneralPoll().getPollTitle()) + .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) + .userVoteResult(userVoteResult) + .topVoteResult(topVoteResult) + .topCandidatePercent(topCandidatePercent) + .allCandidatePercent(allCandidatePercent) + .point(post.getPoint()) + .deadline(post.getGeneralPoll().getDeadline()) + .view(post.getView()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .myPost(myPost) + .build(); } //일반 투표 마감 후 //투표한 후보에 대한 정보 @@ -496,9 +497,9 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B }) .collect(Collectors.toList()); - allCandidatePercent=post.getGeneralPoll().getCandidateList().stream() + allCandidatePercent = post.getGeneralPoll().getCandidateList().stream() .map(candidate -> { - Long candidateId=candidate.getId(); + Long candidateId = candidate.getId(); long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); }) @@ -576,7 +577,6 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .build(); - } //카드 투표 상세 보기 //나노초 단위로 마감 여부 확인 @@ -585,10 +585,10 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B Boolean voteOnGoing = nanosUntilDeadline > 0; //투표 후보 리스트 - List pollOptionDTOList=post.getCardPoll().getCandidateList().stream() + List pollOptionDTOList = post.getCardPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - if(post.getCardPoll().getDeadline().isAfter(LocalDateTime.now())){ - if(engage) { + if (post.getCardPoll().getDeadline().isAfter(LocalDateTime.now())) { + if (engage) { //투표한 후보에 대한 정보 Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() .filter(CardVote -> CardVote.getUser().getId().equals(userId)) @@ -631,7 +631,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B return String.format("%d/%d", selectionCount, totalVotes); }) .collect(Collectors.toList()); - isVote=true; + isVote = true; // 투표수가 가장 많은 후보의 선택률 계산 OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() .mapToDouble(aLong -> (double) aLong.getValue() / totalVotes) @@ -748,9 +748,9 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B }) .collect(Collectors.toList()); - allCandidatePercent=post.getCardPoll().getCandidateList().stream() + allCandidatePercent = post.getCardPoll().getCandidateList().stream() .map(candidate -> { - Long candidateId=candidate.getId(); + Long candidateId = candidate.getId(); long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); }) @@ -829,21 +829,21 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B } //전체 보기 - public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Long userId){ - File userFile=null; - String userImg=null; - Optional userFileOptional=Optional.ofNullable(post.getUser().getFile()); - List userVotePercent=null; - List topCandidatePercent=null; - List allCandidatePercent=null; - - if(userFileOptional.isPresent()){ - userFile = userFileOptional.get(); - userImg=userFile.getUrl(); + public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Long userId) { + File userFile = null; + String userImg = null; + Optional userFileOptional = Optional.ofNullable(post.getUser().getFile()); + List userVotePercent = null; + List topCandidatePercent = null; + List allCandidatePercent = null; + + if (userFileOptional.isPresent()) { + userFile = userFileOptional.get(); + userImg = userFile.getUrl(); } //로컬 db test - if(post.getPostType()==VOTE&&post.getVoteType()==null){ + if (post.getPostType() == VOTE && post.getVoteType() == null) { return PostResponseDTO.PollPostGetResponse.builder() .postId(post.getId()) .postVoteType(null) @@ -855,18 +855,18 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); - List userChoiceList=null; - List topCandidateList=null; - Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); - Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); - Boolean engage=false; - - if(post.getVoteType()==PostVoteType.GENERAL) { - List pollOptionDTOList = post.getGeneralPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - if (!post.getGeneralPoll().getGeneralVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { - engage = true; - } + List userChoiceList = null; + List topCandidateList = null; + Boolean isLike = !post.getPostLikeList().stream().filter(like -> like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + Boolean isComment = !post.getCommentList().stream().filter(like -> like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + Boolean engage = false; + + if (post.getVoteType() == PostVoteType.GENERAL) { + List pollOptionDTOList = post.getGeneralPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); + if (!post.getGeneralPoll().getGeneralVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { + engage = true; + } //일반 투표 마감 전 if (post.getGeneralPoll().getDeadline().isAfter(LocalDateTime.now())) { if (engage) { @@ -899,7 +899,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); - //1등 투표 계산 + //1등 투표 계산 // 투표수가 가장 많은 후보의 선택률 계산 OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() .mapToDouble(entry -> (double) entry.getValue() / totalVotes) @@ -923,9 +923,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); - allCandidatePercent=post.getGeneralPoll().getCandidateList().stream() + allCandidatePercent = post.getGeneralPoll().getCandidateList().stream() .map(candidate -> { - Long candidateId=candidate.getId(); + Long candidateId = candidate.getId(); long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); }) @@ -988,9 +988,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); - allCandidatePercent=post.getGeneralPoll().getCandidateList().stream() + allCandidatePercent = post.getGeneralPoll().getCandidateList().stream() .map(candidate -> { - Long candidateId=candidate.getId(); + Long candidateId = candidate.getId(); long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); }) @@ -1071,9 +1071,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, }) .collect(Collectors.toList()); - allCandidatePercent=post.getGeneralPoll().getCandidateList().stream() + allCandidatePercent = post.getGeneralPoll().getCandidateList().stream() .map(candidate -> { - Long candidateId=candidate.getId(); + Long candidateId = candidate.getId(); long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); }) @@ -1124,16 +1124,16 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } - if(post.getVoteType()==PostVoteType.GAUGE) { + if (post.getVoteType() == PostVoteType.GAUGE) { if (!post.getGaugePoll().getGaugeVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { engage = true; } - OptionaluserGaugeVoteOptional=post.getGaugePoll().getGaugeVoteList().stream() + Optional userGaugeVoteOptional = post.getGaugePoll().getGaugeVoteList().stream() .filter(gaugeVote -> gaugeVote.getUser().getId().equals(userId)) .findFirst(); - Integer userGauge=null; - if(userGaugeVoteOptional.isPresent()){ - userGauge=userGaugeVoteOptional.get().getValue(); + Integer userGauge = null; + if (userGaugeVoteOptional.isPresent()) { + userGauge = userGaugeVoteOptional.get().getValue(); } if (post.getGaugePoll().getDeadline().isAfter(LocalDateTime.now())) { if (engage) { @@ -1275,9 +1275,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, }) .collect(Collectors.toList()); - allCandidatePercent=post.getCardPoll().getCandidateList().stream() + allCandidatePercent = post.getCardPoll().getCandidateList().stream() .map(candidate -> { - Long candidateId=candidate.getId(); + Long candidateId = candidate.getId(); long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); }) @@ -1341,9 +1341,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, }) .collect(Collectors.toList()); - allCandidatePercent=post.getCardPoll().getCandidateList().stream() + allCandidatePercent = post.getCardPoll().getCandidateList().stream() .map(candidate -> { - Long candidateId=candidate.getId(); + Long candidateId = candidate.getId(); long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); }) @@ -1424,9 +1424,9 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, }) .collect(Collectors.toList()); - allCandidatePercent=post.getCardPoll().getCandidateList().stream() + allCandidatePercent = post.getCardPoll().getCandidateList().stream() .map(candidate -> { - Long candidateId=candidate.getId(); + Long candidateId = candidate.getId(); long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return (int) ((double) selectionCount / totalVotes * 100); }) @@ -1476,27 +1476,27 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .build(); } - public static PostResponseDTO.PollPostGetListDTO pollPostGetListDTO(Page postList,Long userId){ + public static PostResponseDTO.PollPostGetListDTO pollPostGetListDTO(Page postList, Long userId) { List pollPostGetListDTO = postList.stream() - .map(post->pollPostGetResponse(post,userId)).collect(Collectors.toList()); + .map(post -> pollPostGetResponse(post, userId)).collect(Collectors.toList()); return PostResponseDTO.PollPostGetListDTO.builder() .pollPostList(pollPostGetListDTO) .isEnd(postList.isLast()) .build(); } - public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post post, Long userId){ + public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post post, Long userId) { Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); - Boolean isLike=!post.getPostLikeList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); - Boolean isComment=!post.getCommentList().stream().filter(like->like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); - File userFile=null; - String userImg=null; - Optional userFileOptional=Optional.ofNullable(post.getUser().getFile()); + Boolean isLike = !post.getPostLikeList().stream().filter(like -> like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + Boolean isComment = !post.getCommentList().stream().filter(like -> like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + File userFile = null; + String userImg = null; + Optional userFileOptional = Optional.ofNullable(post.getUser().getFile()); - if(userFileOptional.isPresent()){ + if (userFileOptional.isPresent()) { userFile = userFileOptional.get(); - userImg=userFile.getUrl(); + userImg = userFile.getUrl(); } return PostResponseDTO.ReviewPostGetResponse.builder() .postId(post.getId()) @@ -1513,16 +1513,16 @@ public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post p .build(); } - public static PostResponseDTO.ReviewPostGetListDTO reviewPostGetListDTO(Page postList,Long userId){ + public static PostResponseDTO.ReviewPostGetListDTO reviewPostGetListDTO(Page postList, Long userId) { List reviewPostGetListDTO = postList.stream() - .map(post->reviewPostGetResponse(post,userId)).collect(Collectors.toList()); + .map(post -> reviewPostGetResponse(post, userId)).collect(Collectors.toList()); return PostResponseDTO.ReviewPostGetListDTO.builder() .reviewPostList(reviewPostGetListDTO) .isEnd(postList.isLast()) .build(); } - public static ParentPostDTO.CandidatePostDTO candidatePostDTO(Post post){ + public static ParentPostDTO.CandidatePostDTO candidatePostDTO(Post post) { Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); return ParentPostDTO.CandidatePostDTO.builder() @@ -1535,16 +1535,16 @@ public static ParentPostDTO.CandidatePostDTO candidatePostDTO(Post post){ .build(); } - public static ParentPostDTO.ParentPostGetListDTO parentPostGetListDTO(Page postList,Long userId){ + public static ParentPostDTO.ParentPostGetListDTO parentPostGetListDTO(Page postList, Long userId) { List parentPostGetListDTO = postList.stream() - .map(post->candidatePostDTO(post)).collect(Collectors.toList()); + .map(post -> candidatePostDTO(post)).collect(Collectors.toList()); return ParentPostDTO.ParentPostGetListDTO.builder() .candidatePostDTOList(parentPostGetListDTO) .isEnd(postList.isLast()) .build(); } - public static PostResponseDTO.MyPostDTO toMyPostResDTO(Post post){ + public static PostResponseDTO.MyPostDTO toMyPostResDTO(Post post) { return PostResponseDTO.MyPostDTO.builder() .postId(post.getId()) .nickName(post.getUser().getNickname()) diff --git a/src/main/java/friend/spring/converter/SseConverter.java b/src/main/java/friend/spring/converter/SseConverter.java index 3cf54fa..2cba39f 100644 --- a/src/main/java/friend/spring/converter/SseConverter.java +++ b/src/main/java/friend/spring/converter/SseConverter.java @@ -6,7 +6,7 @@ import friend.spring.web.dto.SseResponseDTO; public class SseConverter { - public static SseResponseDTO.CommentCreateResDTO toCommentCreateResDTO (Comment comment, AlarmType alarmType) { + public static SseResponseDTO.CommentCreateResDTO toCommentCreateResDTO(Comment comment, AlarmType alarmType) { String userPhoto = null; if (comment.getUser().getFile() != null) { userPhoto = comment.getUser().getFile().getUrl(); @@ -31,7 +31,7 @@ public static SseResponseDTO.CommentCreateResDTO toCommentCreateResDTO (Comment .build(); } - public static SseResponseDTO.VoteFinishResDTO toVoteFinishResDTO(Post post, AlarmType alarmType){ + public static SseResponseDTO.VoteFinishResDTO toVoteFinishResDTO(Post post, AlarmType alarmType) { return SseResponseDTO.VoteFinishResDTO.builder() .postId(post.getId()) .alarmContent(post.getContent()) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index cdf3c72..0783a05 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -199,12 +199,13 @@ public static UserResponseDTO.OAuthResponse toOAuthResponse( } public static User KakaoUser( - KakaoProfile kakaoProfile){ + KakaoProfile kakaoProfile) { return User.builder() .email(kakaoProfile.getKakao_account().getEmail()).build(); } - public static UserResponseDTO.PasswordUpdateRes toUpdatePassword(User user){ + + public static UserResponseDTO.PasswordUpdateRes toUpdatePassword(User user) { return UserResponseDTO.PasswordUpdateRes.builder() .newPassword(user.getPassword()) .build(); diff --git a/src/main/java/friend/spring/domain/Candidate.java b/src/main/java/friend/spring/domain/Candidate.java index df28ea8..d2cab24 100644 --- a/src/main/java/friend/spring/domain/Candidate.java +++ b/src/main/java/friend/spring/domain/Candidate.java @@ -5,6 +5,7 @@ import org.hibernate.Hibernate; import javax.persistence.*; + @Entity @Getter @Builder @@ -31,14 +32,14 @@ public class Candidate extends BaseEntity { private File file; public void setGeneralPoll(General_poll generalPoll) { - this.generalPoll = generalPoll; - if (this.generalPoll != null) { - Hibernate.initialize(this.generalPoll); - if (this.generalPoll.getCandidateList() != null) { - this.generalPoll.getCandidateList().add(this); + this.generalPoll = generalPoll; + if (this.generalPoll != null) { + Hibernate.initialize(this.generalPoll); + if (this.generalPoll.getCandidateList() != null) { + this.generalPoll.getCandidateList().add(this); + } } } -} public void setCardPoll(Card_poll cardPoll) { this.cardPoll = cardPoll; diff --git a/src/main/java/friend/spring/domain/Card_poll.java b/src/main/java/friend/spring/domain/Card_poll.java index b90242c..d2e6d41 100644 --- a/src/main/java/friend/spring/domain/Card_poll.java +++ b/src/main/java/friend/spring/domain/Card_poll.java @@ -8,6 +8,7 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; + @Entity @Getter @Builder @@ -23,15 +24,15 @@ public class Card_poll extends BaseEntity { @Column(nullable = true) @Builder.Default - private Boolean multipleChoice=true; + private Boolean multipleChoice = true; @Column(nullable = true) @Builder.Default - private LocalDateTime deadline= LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. + private LocalDateTime deadline = LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. @Column(nullable = false) @Builder.Default - private Boolean VoteOnGoing=true; + private Boolean VoteOnGoing = true; @Builder.Default @OneToMany(mappedBy = "cardPoll", cascade = CascadeType.ALL) @@ -42,20 +43,22 @@ public class Card_poll extends BaseEntity { private Post post; @Builder.Default - @OneToMany(mappedBy = "cardPoll",cascade = CascadeType.ALL) - private List candidateList=new ArrayList<>(); + @OneToMany(mappedBy = "cardPoll", cascade = CascadeType.ALL) + private List candidateList = new ArrayList<>(); public void setPost(Post post) { this.post = post; } - public void setDeadline(LocalDateTime deadline){ - this.deadline=deadline; + public void setDeadline(LocalDateTime deadline) { + this.deadline = deadline; } - public void setVoteOnGoing(Boolean voteOnGoing){ - this.VoteOnGoing=voteOnGoing; + + public void setVoteOnGoing(Boolean voteOnGoing) { + this.VoteOnGoing = voteOnGoing; } - public void setMultipleChoice(Boolean multipleChoice){ - this.multipleChoice=multipleChoice; + + public void setMultipleChoice(Boolean multipleChoice) { + this.multipleChoice = multipleChoice; } } diff --git a/src/main/java/friend/spring/domain/Card_vote.java b/src/main/java/friend/spring/domain/Card_vote.java index d87c532..7c81807 100644 --- a/src/main/java/friend/spring/domain/Card_vote.java +++ b/src/main/java/friend/spring/domain/Card_vote.java @@ -20,7 +20,7 @@ public class Card_vote extends BaseEntity { @ElementCollection @Builder.Default @Column(nullable = true, length = 100) - private List select_list=new ArrayList(); + private List select_list = new ArrayList(); @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") @@ -37,14 +37,16 @@ public void setSelect_list(List select_list) { this.select_list.clear(); } } - public void setCardPoll(Card_poll cardPoll){ - if(this.cardPoll != null) + + public void setCardPoll(Card_poll cardPoll) { + if (this.cardPoll != null) cardPoll.getCardVoteList().remove(this); this.cardPoll = cardPoll; cardPoll.getCardVoteList().add(this); } - public void setUser(User user){ - if(this.user != null) + + public void setUser(User user) { + if (this.user != null) user.getCardVoteList().remove(this); this.user = user; user.getCardVoteList().add(this); diff --git a/src/main/java/friend/spring/domain/Category.java b/src/main/java/friend/spring/domain/Category.java index 93eafa8..f340f23 100644 --- a/src/main/java/friend/spring/domain/Category.java +++ b/src/main/java/friend/spring/domain/Category.java @@ -18,7 +18,6 @@ public class Category extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false) private String name; diff --git a/src/main/java/friend/spring/domain/File.java b/src/main/java/friend/spring/domain/File.java index cf38e0d..6897136 100644 --- a/src/main/java/friend/spring/domain/File.java +++ b/src/main/java/friend/spring/domain/File.java @@ -30,7 +30,7 @@ public class File extends BaseEntity { // S3에 저장한 이미지 파일 링 @JoinColumn(name = "user_id") private User user; - public void setUrl(String imageUrl){ + public void setUrl(String imageUrl) { this.url = imageUrl; } } diff --git a/src/main/java/friend/spring/domain/Gauge_poll.java b/src/main/java/friend/spring/domain/Gauge_poll.java index 1fd7c7d..9132262 100644 --- a/src/main/java/friend/spring/domain/Gauge_poll.java +++ b/src/main/java/friend/spring/domain/Gauge_poll.java @@ -24,15 +24,15 @@ public class Gauge_poll extends BaseEntity { @Builder.Default @Column(nullable = false) - private Integer gauge =0; + private Integer gauge = 0; @Builder.Default @Column(nullable = true) - private LocalDateTime deadline= LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. + private LocalDateTime deadline = LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. @Column(nullable = false) @Builder.Default - private Boolean VoteOnGoing=true; + private Boolean VoteOnGoing = true; @OneToOne(mappedBy = "gaugePoll", cascade = CascadeType.ALL) @JoinColumn(name = "post_id") @@ -46,12 +46,12 @@ public void setPost(Post post) { this.post = post; } - public void setDeadline(LocalDateTime deadline){ - this.deadline=deadline; + public void setDeadline(LocalDateTime deadline) { + this.deadline = deadline; } - public void setVoteOnGoing(Boolean voteOnGoing){ - this.VoteOnGoing=voteOnGoing; + public void setVoteOnGoing(Boolean voteOnGoing) { + this.VoteOnGoing = voteOnGoing; } public void setGauge(Integer gauge) { diff --git a/src/main/java/friend/spring/domain/Gauge_vote.java b/src/main/java/friend/spring/domain/Gauge_vote.java index f2e3562..c488cf7 100644 --- a/src/main/java/friend/spring/domain/Gauge_vote.java +++ b/src/main/java/friend/spring/domain/Gauge_vote.java @@ -27,14 +27,15 @@ public class Gauge_vote extends BaseEntity { private Gauge_poll gaugePoll; - public void setGaugePoll(Gauge_poll gaugePoll){ - if(this.gaugePoll != null) + public void setGaugePoll(Gauge_poll gaugePoll) { + if (this.gaugePoll != null) gaugePoll.getGaugeVoteList().remove(this); this.gaugePoll = gaugePoll; gaugePoll.getGaugeVoteList().add(this); } - public void setUser(User user){ - if(this.user != null) + + public void setUser(User user) { + if (this.user != null) user.getGaugeVoteList().remove(this); this.user = user; user.getGaugeVoteList().add(this); diff --git a/src/main/java/friend/spring/domain/General_poll.java b/src/main/java/friend/spring/domain/General_poll.java index 6628ee5..21a83e1 100644 --- a/src/main/java/friend/spring/domain/General_poll.java +++ b/src/main/java/friend/spring/domain/General_poll.java @@ -24,15 +24,15 @@ public class General_poll extends BaseEntity { @Column(nullable = true) @Builder.Default - private Boolean multipleChoice=true; + private Boolean multipleChoice = true; @Column(nullable = true) @Builder.Default - private LocalDateTime deadline= LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. + private LocalDateTime deadline = LocalDateTime.now().plusHours(1); // 디폴트 시간 1시간 설정. @Column(nullable = false) @Builder.Default - private Boolean VoteOnGoing=true; + private Boolean VoteOnGoing = true; @Builder.Default @OneToMany(mappedBy = "generalPoll", cascade = CascadeType.ALL) @@ -43,21 +43,23 @@ public class General_poll extends BaseEntity { private Post post; @Builder.Default - @OneToMany(mappedBy = "generalPoll",cascade = CascadeType.ALL) - private List candidateList=new ArrayList<>(); + @OneToMany(mappedBy = "generalPoll", cascade = CascadeType.ALL) + private List candidateList = new ArrayList<>(); public void setPost(Post post) { this.post = post; } - public void setDeadline(LocalDateTime deadline){ - this.deadline=deadline; + public void setDeadline(LocalDateTime deadline) { + this.deadline = deadline; } - public void setVoteOnGoing(Boolean voteOnGoing){ - this.VoteOnGoing=voteOnGoing; + + public void setVoteOnGoing(Boolean voteOnGoing) { + this.VoteOnGoing = voteOnGoing; } - public void setMultipleChoice(Boolean multipleChoice){ - this.multipleChoice=multipleChoice; + + public void setMultipleChoice(Boolean multipleChoice) { + this.multipleChoice = multipleChoice; } } diff --git a/src/main/java/friend/spring/domain/General_vote.java b/src/main/java/friend/spring/domain/General_vote.java index 5e64a57..e4866be 100644 --- a/src/main/java/friend/spring/domain/General_vote.java +++ b/src/main/java/friend/spring/domain/General_vote.java @@ -20,7 +20,7 @@ public class General_vote extends BaseEntity { @ElementCollection @Builder.Default @Column(nullable = true, length = 100) - private List select_list=new ArrayList(); + private List select_list = new ArrayList(); @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") @@ -37,14 +37,16 @@ public void setSelect_list(List select_list) { this.select_list.clear(); } } - public void setGeneralPoll(General_poll generalPoll){ - if(this.generalPoll != null) + + public void setGeneralPoll(General_poll generalPoll) { + if (this.generalPoll != null) generalPoll.getGeneralVoteList().remove(this); this.generalPoll = generalPoll; generalPoll.getGeneralVoteList().add(this); } - public void setUser(User user){ - if(this.user != null) + + public void setUser(User user) { + if (this.user != null) user.getGeneralVoteList().remove(this); this.user = user; user.getGeneralVoteList().add(this); diff --git a/src/main/java/friend/spring/domain/Point.java b/src/main/java/friend/spring/domain/Point.java index 740f6c9..14c058a 100644 --- a/src/main/java/friend/spring/domain/Point.java +++ b/src/main/java/friend/spring/domain/Point.java @@ -25,8 +25,8 @@ public class Point extends BaseEntity { @JoinColumn(name = "user_id") private User user; - public void setUser(User user){ - if(this.user != null) + public void setUser(User user) { + if (this.user != null) user.getPointList().remove(this); this.user = user; user.getPointList().add(this); diff --git a/src/main/java/friend/spring/domain/Post.java b/src/main/java/friend/spring/domain/Post.java index 0538b5e..99795c8 100644 --- a/src/main/java/friend/spring/domain/Post.java +++ b/src/main/java/friend/spring/domain/Post.java @@ -45,7 +45,7 @@ public class Post extends BaseEntity { @Builder.Default @Column(nullable = false) - private Integer view=0; + private Integer view = 0; @Column(nullable = true) @@ -53,7 +53,7 @@ public class Post extends BaseEntity { @Builder.Default @Column(nullable = false) - private Integer isFixed=0; + private Integer isFixed = 0; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") @@ -103,7 +103,7 @@ public class Post extends BaseEntity { private Card_poll cardPoll; @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name="gaugePoll_id") + @JoinColumn(name = "gaugePoll_id") private Gauge_poll gaugePoll; @OneToOne(fetch = FetchType.LAZY) @@ -111,25 +111,24 @@ public class Post extends BaseEntity { private General_poll generalPoll; - - public void setUser(User user){ - if(this.user != null) + public void setUser(User user) { + if (this.user != null) user.getPostList().remove(this); this.user = user; user.getPostList().add(this); } - public void setParentPost(Post parent){ - if(this.parentPost != null) + public void setParentPost(Post parent) { + if (this.parentPost != null) parent.getReviewPostList().remove(this); - this.parentPost=parent; + this.parentPost = parent; parent.getReviewPostList().add(this); } - public void setCategory(Category category){ - if(this.category != null) + public void setCategory(Category category) { + if (this.category != null) category.getPostList().remove(this); - this.category =category; + this.category = category; category.getPostList().add(this); } @@ -159,20 +158,20 @@ public void setCardPoll(Card_poll cardPoll) { } } - public void setTitle(String title){ - this.title=title; + public void setTitle(String title) { + this.title = title; } - public void setContent(String content){ - this.content=content; + public void setContent(String content) { + this.content = content; } - public void setIsFixed(Integer isFixed){ - this.isFixed=isFixed; + public void setIsFixed(Integer isFixed) { + this.isFixed = isFixed; } - public void setStateDel(){ - this.state=PostState.DELETED; + public void setStateDel() { + this.state = PostState.DELETED; } } diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 73a0531..227eb8f 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -63,7 +63,7 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true) @Builder.Default - private Integer point=0; + private Integer point = 0; @Column(nullable = true) private String kakao; @@ -178,12 +178,20 @@ public void setFile(File file) { this.file = file; } - public void setNickname(String nickname){ this.nickname = nickname; } + public void setNickname(String nickname) { + this.nickname = nickname; + } - public void setEmail(String email){this.email = email;} + public void setEmail(String email) { + this.email = email; + } - public void setPhone(String phone){this.phone = phone;} + public void setPhone(String phone) { + this.phone = phone; + } - public void setPassword(String password){this.password = password;} + public void setPassword(String password) { + this.password = password; + } } diff --git a/src/main/java/friend/spring/repository/General_VoteRepository.java b/src/main/java/friend/spring/repository/General_VoteRepository.java index aa7ea7b..f70153a 100644 --- a/src/main/java/friend/spring/repository/General_VoteRepository.java +++ b/src/main/java/friend/spring/repository/General_VoteRepository.java @@ -5,6 +5,6 @@ import java.util.List; -public interface General_VoteRepository extends JpaRepository { +public interface General_VoteRepository extends JpaRepository { List findByUserId(Long user_id); } diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index bf455eb..442be11 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -17,9 +17,13 @@ public interface PostRepository extends JpaRepository { Page findByPostTypeAndState(PostType postType, PostState state, Pageable pageable); - Page findByPostTypeAndStateAndCategory(PostType postType, PostState state,Category category,Pageable pageable); + + Page findByPostTypeAndStateAndCategory(PostType postType, PostState state, Category category, Pageable pageable); + Page findByUserIdAndPostTypeAndState(Long userId, PostType postType, PostState state, Pageable pageable); + Page findAllByUser(User user, PageRequest pageRequest); + Page findByPostTypeAndStateAndCreatedAtAfter(PostType postType, PostState state, LocalDateTime sevenDaysAgo, Pageable pageable); @Query(value = "SELECT p FROM Post p JOIN p.postScrapList s JOIN p.category c WHERE s.user.id = :userId and c.id = :categoryId") diff --git a/src/main/java/friend/spring/repository/UserRepository.java b/src/main/java/friend/spring/repository/UserRepository.java index f9ecd6b..1ee2630 100644 --- a/src/main/java/friend/spring/repository/UserRepository.java +++ b/src/main/java/friend/spring/repository/UserRepository.java @@ -11,9 +11,11 @@ public interface UserRepository extends JpaRepository { Optional findByEmail(String email); + Optional findByNickname(String nickname); // Optional findByEmailAndRole(String email, RoleType roleType); Boolean existsByEmail(String email); + Boolean existsByNickname(String nickname); } diff --git a/src/main/java/friend/spring/security/JwtAuthenticationFilter.java b/src/main/java/friend/spring/security/JwtAuthenticationFilter.java index 96f1389..3d1d0ef 100644 --- a/src/main/java/friend/spring/security/JwtAuthenticationFilter.java +++ b/src/main/java/friend/spring/security/JwtAuthenticationFilter.java @@ -14,7 +14,7 @@ import java.io.IOException; @RequiredArgsConstructor -public class JwtAuthenticationFilter extends OncePerRequestFilter { +public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtTokenProvider jwtTokenProvider; @@ -28,7 +28,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse String token = jwtTokenProvider.resolveToken(request); // validateToken으로 토큰 유효성 검사 - if(token != null && jwtTokenProvider.validateToken(token)) { + if (token != null && jwtTokenProvider.validateToken(token)) { // Redis에 해당 access token logout여부를 확인 String isLogout = (String) redisTemplate.opsForValue().get(token); diff --git a/src/main/java/friend/spring/security/JwtTokenProvider.java b/src/main/java/friend/spring/security/JwtTokenProvider.java index f035be1..4e4229d 100644 --- a/src/main/java/friend/spring/security/JwtTokenProvider.java +++ b/src/main/java/friend/spring/security/JwtTokenProvider.java @@ -54,7 +54,7 @@ protected void init() { // JWT Access 토큰 생성 public TokenDTO createAccessToken(String email) { // 토큰 유효시간 30분 - long tokenValidTime =48 * 60 * 60 * 1000L; + long tokenValidTime = 48 * 60 * 60 * 1000L; Optional user = userRepository.findByEmail(email); @@ -97,7 +97,7 @@ public TokenDTO createRefreshToken(String email) { .signWith(SignatureAlgorithm.HS256, secretKey) // 사용할 암호화 알고리즘과 signature 에 들어갈 secretkey 값 설정 .claim("types", "rtk") .compact(); - return new TokenDTO(String.valueOf(TokenType.rtk),token, expiresTime); + return new TokenDTO(String.valueOf(TokenType.rtk), token, expiresTime); } // JWT 토큰에서 인증 정보 조회 @@ -118,7 +118,7 @@ public String resolveAccessToken(HttpServletRequest request) { // 토큰 재발급 때 Header에 rtk를 넣어 요청, 나머지 경우 atk 사용 public String resolveToken(HttpServletRequest request) { - if (request.getHeader("rtk") != null){ + if (request.getHeader("rtk") != null) { return request.getHeader("rtk"); } else { return request.getHeader("atk"); @@ -129,7 +129,7 @@ public String resolveToken(HttpServletRequest request) { public boolean validateToken(String jwtToken) { try { Jws claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwtToken); // 토큰의 payload(claim) // Access 토큰의 경우 redis 까지 검사 - if (claims.getBody().get("types").equals("atk")) { + if (claims.getBody().get("types").equals("atk")) { Object isLogOut = redisTemplate.opsForValue().get(jwtToken); // token 을 key 로 value 가져옴 (null 이면 유효 토큰, logout 이면 유효하지 않은 토큰) // 로그인 시 redis 에 email : refreshtoken 형태로 저장 // 로그아웃 시 redis 에 accesstoken : logout 형태로 저장 @@ -141,7 +141,7 @@ public boolean validateToken(String jwtToken) { // Refresh 토큰 유효성 검사 return !claims.getBody().getExpiration().before(new Date()); // 만료안됐으면 true, 만료됐으면 false } - }catch (Exception e) { + } catch (Exception e) { return false; } } @@ -151,10 +151,11 @@ public Date getExpireTime(String jwtToken) { Jws claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwtToken); return claims.getBody().getExpiration(); } + // 토큰에서 회원정보 추출 - userIdx 추출 public Long getCurrentUser(HttpServletRequest request) throws GeneralException { // userIdx 가져오기 String jwtToken = resolveAccessToken(request); // Request의 header에서 Access 토큰 추출 - if(!validateToken(jwtToken)) { + if (!validateToken(jwtToken)) { throw new GeneralException(INVALID_JWT); } diff --git a/src/main/java/friend/spring/security/TokenType.java b/src/main/java/friend/spring/security/TokenType.java index c35cded..1c315f0 100644 --- a/src/main/java/friend/spring/security/TokenType.java +++ b/src/main/java/friend/spring/security/TokenType.java @@ -2,5 +2,4 @@ public enum TokenType { atk, rtk -} - +} \ No newline at end of file diff --git a/src/main/java/friend/spring/service/AlarmServiceImpl.java b/src/main/java/friend/spring/service/AlarmServiceImpl.java index 5ba7068..c6962b3 100644 --- a/src/main/java/friend/spring/service/AlarmServiceImpl.java +++ b/src/main/java/friend/spring/service/AlarmServiceImpl.java @@ -20,15 +20,16 @@ @Service @RequiredArgsConstructor @Transactional -public class AlarmServiceImpl implements AlarmService{ +public class AlarmServiceImpl implements AlarmService { private final UserRepository userRepository; private final AlarmRepository alarmRepository; private final UserService userService; private final JwtTokenProvider jwtTokenProvider; + @Override public void checkAlarm(boolean flag) { - if (!flag){ + if (!flag) { throw new AlarmHandler(ErrorStatus.ALARM_NOT_FOUND); } } diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index dac86fd..3199432 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -12,11 +12,15 @@ public interface CommentService { void checkComment(Boolean flag); + void checkCommentLike(Boolean flag); + void checkCommentChoice(Boolean flag); + void checkSelectCommentAnotherUser(Boolean flag); void checkCommentWriterUser(Boolean flag); + public Comment createComment(Long postId, CommentRequestDTO.commentCreateReq requestBody, HttpServletRequest request); Comment_like likeComment(Long postId, Long commentId, HttpServletRequest request); diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index fcfb1e9..6863c52 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -253,7 +253,6 @@ public Boolean checkIsSelected(Comment comment) { } - @Override public void dislikeComment(Long postId, Long commentId, HttpServletRequest request) { Long userId = jwtTokenProvider.getCurrentUser(request); @@ -372,7 +371,7 @@ public void editComment(Long postId, Long commentId, CommentRequestDTO.commentEd @Override public Page getMyCommentList(Long userId, Integer page) { Optional optionalUser = userRepository.findById(userId); - if (optionalUser.isEmpty()){ + if (optionalUser.isEmpty()) { userService.checkUser(false); } User user = optionalUser.get(); diff --git a/src/main/java/friend/spring/service/EmailService.java b/src/main/java/friend/spring/service/EmailService.java index fe1a8d3..4cfcedf 100644 --- a/src/main/java/friend/spring/service/EmailService.java +++ b/src/main/java/friend/spring/service/EmailService.java @@ -103,7 +103,7 @@ public String passwordEmail(String email) { } - public void voteFinishEmail(Post post){ + public void voteFinishEmail(Post post) { String setFrom = "gominchingu@gmail.com"; // email-config에 설정한 자신의 이메일 주소를 입력 String toMail = post.getUser().getEmail(); String title = "고민친구 투표 마감 알림 이메일 입니다."; diff --git a/src/main/java/friend/spring/service/JwtTokenServiceImpl.java b/src/main/java/friend/spring/service/JwtTokenServiceImpl.java index 2bfbc78..f215367 100644 --- a/src/main/java/friend/spring/service/JwtTokenServiceImpl.java +++ b/src/main/java/friend/spring/service/JwtTokenServiceImpl.java @@ -9,11 +9,12 @@ @Service @RequiredArgsConstructor -public class JwtTokenServiceImpl implements JwtTokenService{ +public class JwtTokenServiceImpl implements JwtTokenService { private final JwtTokenProvider jwtTokenProvider; + @Override @Transactional - public Long JwtToId(HttpServletRequest request){ + public Long JwtToId(HttpServletRequest request) { return jwtTokenProvider.getCurrentUser(request); } diff --git a/src/main/java/friend/spring/service/MyPageService.java b/src/main/java/friend/spring/service/MyPageService.java index c3c95ef..e128fb1 100644 --- a/src/main/java/friend/spring/service/MyPageService.java +++ b/src/main/java/friend/spring/service/MyPageService.java @@ -13,9 +13,10 @@ public interface MyPageService { void checkPost(Boolean flag); + List getCategoryList(Long userId); - Page getAllPostList(Long userId, Integer page, Integer sort); + Page getAllPostList(Long userId, Integer page, Integer sort); void editUserImage(MultipartFile file, HttpServletRequest request); @@ -24,12 +25,15 @@ public interface MyPageService { User editUserName(Long userId, MyPageRequestDTO.ProfileEditNameReq profileEditNameReq); User editUserEmail(Long userId, MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq); + User editUserPhone(Long userId, MyPageRequestDTO.ProfileEditPhoneReq profileEditPhoneReq); User editUserPassword(Long userId, MyPageRequestDTO.ProfileEditPasswordReq profileEditPasswordReq); + User editUserSecurity(Long userId, MyPageRequestDTO.ProfileEditSecurityReq profileEditSecurityReq); Inquiry createInquiry(Long userId, MyPageRequestDTO.MyInquiryReq myInquiryReq); + Page getCategoryDetailList(Long userId, Long categoryId, Integer page); Category getCategory(Long categoryId); diff --git a/src/main/java/friend/spring/service/MyPageServiceImpl.java b/src/main/java/friend/spring/service/MyPageServiceImpl.java index ef12abe..3ec22f6 100644 --- a/src/main/java/friend/spring/service/MyPageServiceImpl.java +++ b/src/main/java/friend/spring/service/MyPageServiceImpl.java @@ -33,7 +33,7 @@ @RequiredArgsConstructor @Transactional @Slf4j -public class MyPageServiceImpl implements MyPageService{ +public class MyPageServiceImpl implements MyPageService { private final UserRepository userRepository; private final PostService postService; @@ -56,6 +56,7 @@ public void checkPost(Boolean flag) { throw new PostHandler(ErrorStatus.POST_CATGORY_NOT_FOUND); } } + //저장한 게시물 @Override public List getCategoryList(Long userId) { @@ -68,19 +69,17 @@ public List getCategoryList(Long userId) { .map(Post_scrap::getPost).filter(Objects::nonNull) .map(Post::getCategory).filter(Objects::nonNull).distinct().collect(Collectors.toList()); return categoryList; - } + } @Override public Page getAllPostList(Long userId, Integer page, Integer sort) { - if (sort == 0){ + if (sort == 0) { Page scrapListByView = postScrapRepository.findPostsByUserIdOrderByPostViewDesc(userId, PageRequest.of(page, 10)); return scrapListByView; - } - else if (sort == 1){ + } else if (sort == 1) { Page scrapListByRecent = postScrapRepository.findPostsByUserIdOrderByCreatedAtDesc(userId, PageRequest.of(page, 10)); return scrapListByRecent; - } - else return null; + } else return null; } @Override @@ -123,10 +122,10 @@ public User editUserEmail(Long userId, MyPageRequestDTO.ProfileEditEmailReq prof User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); List all = userRepository.findAll(); all.forEach(eachUser -> { - if (eachUser.getEmail().equals(profileEditEmailReq.getChangeEmail())) { - throw new GeneralException(ErrorStatus.USER_EXISTS_EMAIL); - } - }); + if (eachUser.getEmail().equals(profileEditEmailReq.getChangeEmail())) { + throw new GeneralException(ErrorStatus.USER_EXISTS_EMAIL); + } + }); user.setEmail(profileEditEmailReq.getChangeEmail()); return user; } @@ -141,10 +140,10 @@ public User editUserPhone(Long userId, MyPageRequestDTO.ProfileEditPhoneReq prof @Override public User editUserPassword(Long userId, MyPageRequestDTO.ProfileEditPasswordReq profileEditPasswordReq) { User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); - if (!encoder.matches(profileEditPasswordReq.getCurPassword(), user.getPassword())){ + if (!encoder.matches(profileEditPasswordReq.getCurPassword(), user.getPassword())) { throw new GeneralException(ErrorStatus.PASSWORD_INCORRECT); } - if (!profileEditPasswordReq.getChangePassword().equals(profileEditPasswordReq.getCheckPassword())){ + if (!profileEditPasswordReq.getChangePassword().equals(profileEditPasswordReq.getCheckPassword())) { throw new GeneralException(ErrorStatus.PASSWORD_CHECK_INCORRECT); } String encode = encoder.encode(profileEditPasswordReq.getChangePassword()); @@ -196,7 +195,7 @@ public Page getNoticeList(Long userId, Integer page) { @Override public User checkAdmin(Long adminId) { User user = userRepository.findById(adminId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); - if (user.getRole() == RoleType.USER){ + if (user.getRole() == RoleType.USER) { throw new GeneralException(ErrorStatus.NOT_ADMIN); } return user; diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index 36fa8db..d2b7263 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -10,13 +10,14 @@ public interface PostQueryService { Post getPostDetail(Long postId); + Boolean checkEngage(Long userId, Long postId); Post ParentPost(Long parentid); Optional findPost(Long postId); - Page getPostList(Integer page,Integer size, String category); + Page getPostList(Integer page, Integer size, String category); Page getReviewList(Integer page, Integer size, Integer arrange); diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 539d7c6..aa55538 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -26,7 +26,7 @@ @Service @RequiredArgsConstructor -public class PostQueryServiceImpl implements PostQueryService{ +public class PostQueryServiceImpl implements PostQueryService { private final PostRepository postRepository; private final UserRepository userRepository; private final General_VoteRepository generalVoteRepository; @@ -34,44 +34,45 @@ public class PostQueryServiceImpl implements PostQueryService{ private final Card_VoteRepository cardVoteRepository; private final CategoryRepository categoryRepository; private final JwtTokenProvider jwtTokenProvider; + @Override @Transactional - public Post getPostDetail(Long postId){ - Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); - post.setView(post.getView()+1); + public Post getPostDetail(Long postId) { + Post post = postRepository.findById(postId).orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + post.setView(post.getView() + 1); return post; } @Override - public Boolean checkEngage(Long postId,Long userId){ - Optional postOptional=postRepository.findById(postId); + public Boolean checkEngage(Long postId, Long userId) { + Optional postOptional = postRepository.findById(postId); Post post = postOptional.get(); Boolean engage; - if(post.getUser().getId().equals(userId)){ + if (post.getUser().getId().equals(userId)) { return true; } - if(post.getPostType()== PostType.VOTE){ - if(post.getVoteType()== PostVoteType.GENERAL){ - List vote=generalVoteRepository.findByUserId(userId); - Boolean isIn=vote.stream().filter(pollPost->pollPost.getGeneralPoll()==post.getGeneralPoll()).collect(Collectors.toList()).isEmpty(); + if (post.getPostType() == PostType.VOTE) { + if (post.getVoteType() == PostVoteType.GENERAL) { + List vote = generalVoteRepository.findByUserId(userId); + Boolean isIn = vote.stream().filter(pollPost -> pollPost.getGeneralPoll() == post.getGeneralPoll()).collect(Collectors.toList()).isEmpty(); if (!isIn) { // 목록이 비어 있지 않으면 true를 반환 return true; } } } - if(post.getPostType()== PostType.VOTE){ - if(post.getVoteType()== PostVoteType.CARD){ - List vote=cardVoteRepository.findByUserId(userId); - Boolean isIn=vote.stream().filter(pollPost->pollPost.getCardPoll()==post.getCardPoll()).collect(Collectors.toList()).isEmpty(); + if (post.getPostType() == PostType.VOTE) { + if (post.getVoteType() == PostVoteType.CARD) { + List vote = cardVoteRepository.findByUserId(userId); + Boolean isIn = vote.stream().filter(pollPost -> pollPost.getCardPoll() == post.getCardPoll()).collect(Collectors.toList()).isEmpty(); if (!isIn) { // 목록이 비어 있지 않으면 true를 반환 return true; } } } - if(post.getPostType()== PostType.VOTE){ - if(post.getVoteType()== PostVoteType.GAUGE){ - List vote=gaugeVoteRepository.findByUserId(userId); - Boolean isIn=vote.stream().filter(pollPost->pollPost.getGaugePoll()==post.getGaugePoll()).collect(Collectors.toList()).isEmpty(); + if (post.getPostType() == PostType.VOTE) { + if (post.getVoteType() == PostVoteType.GAUGE) { + List vote = gaugeVoteRepository.findByUserId(userId); + Boolean isIn = vote.stream().filter(pollPost -> pollPost.getGaugePoll() == post.getGaugePoll()).collect(Collectors.toList()).isEmpty(); if (!isIn) { // 목록이 비어 있지 않으면 true를 반환 return true; } @@ -82,8 +83,8 @@ public Boolean checkEngage(Long postId,Long userId){ @Override @Transactional - public Post ParentPost(Long parentid){ - Optional parentPostOptional=postRepository.findById(parentid); + public Post ParentPost(Long parentid) { + Optional parentPostOptional = postRepository.findById(parentid); return parentPostOptional.get().getParentPost(); } @@ -94,19 +95,20 @@ public Optional findPost(Long postId) { @Override @Transactional - public Page getPostList(Integer page,Integer size,String category){ - if(category.equals("모두")){ - Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); - return postRepository.findByPostTypeAndState(PostType.VOTE, PostState.POSTING, pageable);} + public Page getPostList(Integer page, Integer size, String category) { + if (category.equals("모두")) { + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); + return postRepository.findByPostTypeAndState(PostType.VOTE, PostState.POSTING, pageable); + } Category category1 = categoryRepository.findByName(category); Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); - return postRepository.findByPostTypeAndStateAndCategory(PostType.VOTE, PostState.POSTING,category1, pageable); + return postRepository.findByPostTypeAndStateAndCategory(PostType.VOTE, PostState.POSTING, category1, pageable); } @Override @Transactional - public Page getReviewList(Integer page, Integer size, Integer arrange){ - if(arrange==1){ + public Page getReviewList(Integer page, Integer size, Integer arrange) { + if (arrange == 1) { Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); return postRepository.findByPostTypeAndState(PostType.REVIEW, PostState.POSTING, pageable); } @@ -116,28 +118,28 @@ public Page getReviewList(Integer page, Integer size, Integer arrange){ @Override @Transactional - public Page getParentPostList(Integer page, Integer size, HttpServletRequest request){ + public Page getParentPostList(Integer page, Integer size, HttpServletRequest request) { Long userId = jwtTokenProvider.getCurrentUser(request); Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); // List userPost = postRepository.findByUserId(userId); - Page allPost= postRepository.findByUserIdAndPostTypeAndState(userId, PostType.VOTE, PostState.POSTING, pageable); - List filterEndPost=allPost.getContent().stream() - .filter(post->{ - LocalDateTime deadline=null; - switch (post.getVoteType()){ + Page allPost = postRepository.findByUserIdAndPostTypeAndState(userId, PostType.VOTE, PostState.POSTING, pageable); + List filterEndPost = allPost.getContent().stream() + .filter(post -> { + LocalDateTime deadline = null; + switch (post.getVoteType()) { case GENERAL: - deadline=post.getGeneralPoll().getDeadline(); + deadline = post.getGeneralPoll().getDeadline(); break; case GAUGE: - deadline=post.getGaugePoll().getDeadline(); + deadline = post.getGaugePoll().getDeadline(); break; case CARD: - deadline=post.getCardPoll().getDeadline(); + deadline = post.getCardPoll().getDeadline(); break; } - return deadline !=null&&deadline.isBefore(LocalDateTime.now()); + return deadline != null && deadline.isBefore(LocalDateTime.now()); }).collect(Collectors.toList()); - return new PageImpl<>(filterEndPost,pageable, filterEndPost.size()); + return new PageImpl<>(filterEndPost, pageable, filterEndPost.size()); } diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index 042b0fe..fc4034d 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -29,7 +29,7 @@ public interface PostService { Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user); - void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId); + void editPost(Long postId, PostRequestDTO.PostEditReq request, Long userId); void deletePost(Long postId, Long userId); diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index b075605..d29f477 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -32,7 +32,7 @@ @Service @RequiredArgsConstructor -public class PostServiceImpl implements PostService{ +public class PostServiceImpl implements PostService { private final PostRepository postRepository; private final General_PollRepository generalPollRepository; @@ -67,7 +67,7 @@ public void checkPostWriterUser(Boolean flag) { @Override public Boolean checkPoint(PostRequestDTO.AddPostDTO request, User user) { - if(request.getPoint()>user.getPoint()){ + if (request.getPoint() > user.getPoint()) { return Boolean.FALSE; } return Boolean.TRUE; @@ -96,36 +96,36 @@ public void checkPostScrap(Boolean flag) { public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest request2) { Long userId = jwtTokenProvider.getCurrentUser(request2); - Post newPost= PostConverter.toPost(request); - User user=userRepository.findById(userId) - .orElseThrow(()->new GeneralException(USER_NOT_FOUND)); + Post newPost = PostConverter.toPost(request); + User user = userRepository.findById(userId) + .orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); newPost.setUser(user); // 글 첨부파일 사진 저장 if (request.getFileBase64List() != null) { s3Service.uploadPostImagesBase64(request.getFileBase64List(), S3ImageType.POST, newPost); } - LocalDateTime deadline=request.getDeadline(); - if(request.getDeadline()==null){ - deadline=LocalDateTime.now().plusHours(1); + LocalDateTime deadline = request.getDeadline(); + if (request.getDeadline() == null) { + deadline = LocalDateTime.now().plusHours(1); } //일반 투표 api - if(newPost.getPostType()==VOTE){ + if (newPost.getPostType() == VOTE) { newPost.setCategory(categoryRepository.findByName(request.getCategory())); } - if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL){ + if (newPost.getPostType() == VOTE && newPost.getVoteType() == GENERAL) { //포인트 차감 관련 코드 - if(request.getPoint()!=null) { + if (request.getPoint() != null) { if (!checkPoint(request, user)) { throw new GeneralException(NOT_ENOUGH_POINT); } user.setPoint(user.getPoint() - request.getPoint()); - Point newPoint=Point.builder() + Point newPoint = Point.builder() .amount(request.getPoint() * -1) // 차감이므로 -1 곱해서 음수로 변환 - .content("일반 투표 작성에 대한 "+request.getPoint()+" 포인트 차감") + .content("일반 투표 작성에 대한 " + request.getPoint() + " 포인트 차감") .build(); newPoint.setUser(user); pointRepository.save(newPoint); @@ -135,7 +135,7 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque .pollTitle(request.getPollTitle()) .deadline(deadline) .build(); - if(request.getMultipleChoice()!=null){ + if (request.getMultipleChoice() != null) { generalPoll.setMultipleChoice(request.getMultipleChoice()); } newPost.setGeneralPoll(generalPoll); @@ -143,22 +143,22 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque } //카드 투표 api - if(newPost.getPostType()==VOTE&&newPost.getVoteType()==CARD){ + if (newPost.getPostType() == VOTE && newPost.getVoteType() == CARD) { //포인트 차감 관련 코드 - if(request.getPoint()!=null) { + if (request.getPoint() != null) { if (!checkPoint(request, user)) { throw new GeneralException(NOT_ENOUGH_POINT); } user.setPoint(user.getPoint() - request.getPoint()); - Point newPoint=Point.builder() + Point newPoint = Point.builder() .amount(request.getPoint() * -1) - .content("게이지 투표 등록에 대한 "+request.getPoint()+" 포인트 차감") + .content("게이지 투표 등록에 대한 " + request.getPoint() + " 포인트 차감") .build(); newPoint.setUser(user); pointRepository.save(newPoint); } - if(!checkPoint(request, user)&&request.getPoint()!=null){ + if (!checkPoint(request, user) && request.getPoint() != null) { throw new GeneralException(NOT_ENOUGH_POINT); } @@ -166,29 +166,29 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque .pollTitle(request.getPollTitle()) .deadline(deadline) .build(); - if(request.getMultipleChoice()!=null){ + if (request.getMultipleChoice() != null) { cardPoll.setMultipleChoice(request.getMultipleChoice()); } newPost.setCardPoll(cardPoll); cardPollRepository.save(cardPoll); } //게이지 투표 api - if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GAUGE){ + if (newPost.getPostType() == VOTE && newPost.getVoteType() == GAUGE) { //포인트 차감 관련 코드 - if(request.getPoint()!=null) { + if (request.getPoint() != null) { if (!checkPoint(request, user)) { throw new GeneralException(NOT_ENOUGH_POINT); } user.setPoint(user.getPoint() - request.getPoint()); - Point newPoint=Point.builder() + Point newPoint = Point.builder() .amount(request.getPoint() * -1) - .content("카드 투표 등록에 대한 "+request.getPoint()+" 포인트 차감") + .content("카드 투표 등록에 대한 " + request.getPoint() + " 포인트 차감") .build(); newPoint.setUser(user); pointRepository.save(newPoint); } - if(!checkPoint(request, user)&&request.getPoint()!=null){ + if (!checkPoint(request, user) && request.getPoint() != null) { throw new GeneralException(NOT_ENOUGH_POINT); } @@ -202,10 +202,10 @@ public Post joinPost(PostRequestDTO.AddPostDTO request, HttpServletRequest reque gaugePollRepository.save(gaugePoll); } - if(newPost.getPostType()==REVIEW&&request.getParent_id()!=null){ - Post parent=postRepository.findById(request.getParent_id()) - .orElseThrow(()->new GeneralException(POST_NOT_FOUND)); - if(!userId.equals(parent.getUser().getId())){ + if (newPost.getPostType() == REVIEW && request.getParent_id() != null) { + Post parent = postRepository.findById(request.getParent_id()) + .orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); + if (!userId.equals(parent.getUser().getId())) { throw new GeneralException(POST_NOT_CORRECT_USER); } newPost.setParentPost(parent); @@ -242,7 +242,7 @@ public Candidate createCandidate(Long postId, CandidateRequestDTO.AddCandidateRe } // 일반 투표 - if(newPost.getPostType()==VOTE&&newPost.getVoteType()==GENERAL) { + if (newPost.getPostType() == VOTE && newPost.getVoteType() == GENERAL) { General_poll generalPoll = generalPollRepository.findById(newPost.getGeneralPoll().getId()).orElseThrow(() -> new GeneralException(POST_GENERAL_POLL_NOT_FOUND)); candidate.setGeneralPoll(generalPoll); } @@ -257,16 +257,16 @@ public Candidate createCandidate(Long postId, CandidateRequestDTO.AddCandidateRe @Override @Transactional - public void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId){ + public void editPost(Long postId, PostRequestDTO.PostEditReq request, Long userId) { User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); - Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); - if(!user.getId().equals(post.getUser().getId())){ + Post post = postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); + if (!user.getId().equals(post.getUser().getId())) { throw new GeneralException(POST_NOT_CORRECT_USER); } - if(post.getIsFixed()>=2){ + if (post.getIsFixed() >= 2) { throw new GeneralException(TOO_MUCH_FIXED); } - if(!(request.getDeadline()==null)) { + if (!(request.getDeadline() == null)) { LocalDateTime currentDeadLine; if (post.getVoteType() == GENERAL) { currentDeadLine = post.getGeneralPoll().getDeadline(); @@ -285,7 +285,7 @@ public void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId if (request.getDeadline().isBefore(LocalDateTime.now())) { throw new GeneralException(DEADLINE_LIMIT); } - if (!(daysUntilDeadline <= 30)){ + if (!(daysUntilDeadline <= 30)) { throw new GeneralException(DEADLINE_LIMIT); } post.getCardPoll().setDeadline(request.getDeadline()); @@ -302,7 +302,7 @@ public void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId post.getGaugePoll().setDeadline(request.getDeadline()); } } - if(!request.getVoteOnGoing()){ + if (!request.getVoteOnGoing()) { if (post.getVoteType() == GENERAL) { post.getGeneralPoll().setVoteOnGoing(false); } @@ -315,15 +315,15 @@ public void editPost(Long postId,PostRequestDTO.PostEditReq request, Long userId } post.setTitle(request.getTitle()); post.setContent(request.getContent()); - post.setIsFixed(post.getIsFixed()+1); + post.setIsFixed(post.getIsFixed() + 1); } @Override @Transactional public void deletePost(Long postId, Long userId) { User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); - Post post=postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); - if(!user.getId().equals(post.getUser().getId())){ + Post post = postRepository.findById(postId).orElseThrow(() -> new GeneralException(POST_NOT_FOUND)); + if (!user.getId().equals(post.getUser().getId())) { throw new GeneralException(POST_NOT_CORRECT_USER); } post.setStateDel(); @@ -334,7 +334,7 @@ public void deletePost(Long postId, Long userId) { @Override public Page getMyPostList(Long userId, Integer page) { Optional user = userRepository.findById(userId); - if(user.isEmpty()){ + if (user.isEmpty()) { throw new UserHandler(ErrorStatus.USER_NOT_FOUND); } @@ -405,7 +405,7 @@ public PostResponseDTO.PollPostGetListDTO getBestPosts(Integer page, Integer siz Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "point")); Page bestPostPage = postRepository.findByPostTypeAndStateAndCreatedAtAfter(PostType.VOTE, PostState.POSTING, minusDays, pageable); - return PostConverter.pollPostGetListDTO(bestPostPage,userId); + return PostConverter.pollPostGetListDTO(bestPostPage, userId); } @Override @@ -419,7 +419,7 @@ public PostResponseDTO.PollPostGetListDTO getRecentPosts(Integer page, Integer s Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); Page recentPostPage = postRepository.findByPostTypeAndState(PostType.VOTE, PostState.POSTING, pageable); - return PostConverter.pollPostGetListDTO(recentPostPage,userId); + return PostConverter.pollPostGetListDTO(recentPostPage, userId); } @Override diff --git a/src/main/java/friend/spring/service/SchedulerService.java b/src/main/java/friend/spring/service/SchedulerService.java index 91fc8fc..5423177 100644 --- a/src/main/java/friend/spring/service/SchedulerService.java +++ b/src/main/java/friend/spring/service/SchedulerService.java @@ -26,6 +26,7 @@ public class SchedulerService { private final EmailService emailService; private final SseService notificationService; private final AlarmRepository alarmRepository; + // 투표 마감 // (1시간마다 검사해서 투표 마감 날짜가 지나면 닫히도록 할 예정) @Transactional @@ -33,7 +34,7 @@ public class SchedulerService { @Scheduled(cron = "0 0/1 * * * *", zone = "Asia/Seoul") // 매 분마다 실행 -> 매 시간마다 실행으로 변경 예정 public void deleteVote() { List postList = postRepository.findAll(); - if (postList.isEmpty()){ + if (postList.isEmpty()) { throw new GeneralException(ErrorStatus.POST_NOT_FOUND); } LocalDateTime now = LocalDateTime.now(); diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index 93f50b6..29f4b6c 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -13,13 +13,22 @@ public interface UserService { User joinUser(UserRequestDTO.UserJoinRequest userJoinRequest); + List login(UserRequestDTO.UserLoginRequest userLoginRequest); + User findMyPage(Long id); + void checkUser(Boolean flag); + Integer pointCheck(Long id); + Level nextLevel(Long id); + String logout(HttpServletRequest request); + List reissue(HttpServletRequest request); + User updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwordUpdateReq); + String getEmail(HttpServletRequest request); } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 7ab9640..6b0ada1 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -197,13 +197,14 @@ public User updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwo throw new GeneralException(ErrorStatus.PASSWORD_CHECK_INCORRECT); } - // 새로운 비밀번호가 null이 아닌 경우, 사용자의 비밀번호를 새로운 값으로 업데이트 + // 새로운 비밀번호가 null이 아닌 경우, 사용자의 비밀번호를 새로운 값으로 업데이트 if (newPassword != null) { user.setPassword(encoder.encode(newPassword)); } userRepository.save(user); return user; } + // Request 의 Header 에서 email 값 추출 "email" : "gominchingu@gmail.com" public String getEmail(HttpServletRequest request) { return request.getHeader("email"); diff --git a/src/main/java/friend/spring/service/VoteService.java b/src/main/java/friend/spring/service/VoteService.java index 58ce80a..391a8d8 100644 --- a/src/main/java/friend/spring/service/VoteService.java +++ b/src/main/java/friend/spring/service/VoteService.java @@ -7,8 +7,9 @@ public interface VoteService { - General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request,Long PostId, Long userId); - Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request,Long PostId, Long userId); + General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long PostId, Long userId); + + Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long PostId, Long userId); Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request, Long PostId, Long userId); diff --git a/src/main/java/friend/spring/service/VoteServiceImpl.java b/src/main/java/friend/spring/service/VoteServiceImpl.java index 6805b26..faa2c6a 100644 --- a/src/main/java/friend/spring/service/VoteServiceImpl.java +++ b/src/main/java/friend/spring/service/VoteServiceImpl.java @@ -19,7 +19,7 @@ @Service @RequiredArgsConstructor -public class VoteServiceImpl implements VoteService{ +public class VoteServiceImpl implements VoteService { private final UserRepository userRepository; private final General_VoteRepository generalVoteRepository; private final Gauge_VoteRepository gaugeVoteRepository; @@ -27,6 +27,7 @@ public class VoteServiceImpl implements VoteService{ private final PostRepository postRepository; private final PointRepository pointRepository; private final Gauge_PollRepository gaugePollRepository; + @Override @Transactional public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request, Long PostId, Long userId) { @@ -35,14 +36,14 @@ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request .orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); newGeneralVote.setUser(user); - Post post=postRepository.findById(PostId) - .orElseThrow(()-> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + Post post = postRepository.findById(PostId) + .orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); - if(post.getGeneralPoll().getGeneralVoteList().stream().anyMatch(generalVote -> generalVote.getUser().getId().equals(userId))){ + if (post.getGeneralPoll().getGeneralVoteList().stream().anyMatch(generalVote -> generalVote.getUser().getId().equals(userId))) { throw new GeneralException(ErrorStatus.ALREADY_VOTE); } - General_poll generalPoll=post.getGeneralPoll(); + General_poll generalPoll = post.getGeneralPoll(); newGeneralVote.setGeneralPoll(generalPoll); List selectedCandidateIds = request.getSelectList(); @@ -62,14 +63,14 @@ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request LocalDateTime now = LocalDateTime.now(); long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGeneralPoll().getDeadline()); Boolean voteOnGoing = nanosUntilDeadline > 0; - if(!voteOnGoing){ + if (!voteOnGoing) { throw new GeneralException(ErrorStatus.DEADLINE_OVER); } user.setPoint(user.getPoint() + 5); - Point newPoint=Point.builder() + Point newPoint = Point.builder() .amount(5) - .content("일반 투표에 대한 "+5+" 포인트 획득") + .content("일반 투표에 대한 " + 5 + " 포인트 획득") .build(); newPoint.setUser(user); pointRepository.save(newPoint); @@ -79,64 +80,64 @@ public General_vote castGeneralVote(VoteRequestDTO.GeneralVoteRequestDTO request @Override @Transactional - public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long PostId, Long userId){ + public Gauge_vote castGaugeVote(VoteRequestDTO.GaugeVoteRequestDTO request, Long PostId, Long userId) { Gauge_vote newGaugeVote = VoteConverter.toGaugeVote(request); User user = userRepository.findById(userId) .orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); newGaugeVote.setUser(user); - Post post=postRepository.findById(PostId) - .orElseThrow(()-> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + Post post = postRepository.findById(PostId) + .orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); - if(post.getGaugePoll().getGaugeVoteList().stream().anyMatch(gaugeVote -> gaugeVote.getUser().getId().equals(userId))){ + if (post.getGaugePoll().getGaugeVoteList().stream().anyMatch(gaugeVote -> gaugeVote.getUser().getId().equals(userId))) { throw new GeneralException(ErrorStatus.ALREADY_VOTE); } - Gauge_poll gaugePoll=post.getGaugePoll(); + Gauge_poll gaugePoll = post.getGaugePoll(); newGaugeVote.setGaugePoll(gaugePoll); - //나노초 단위로 마감 여부 확인 LocalDateTime now = LocalDateTime.now(); long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGaugePoll().getDeadline()); Boolean voteOnGoing = nanosUntilDeadline > 0; - if(!voteOnGoing){ + if (!voteOnGoing) { throw new GeneralException(ErrorStatus.DEADLINE_OVER); } user.setPoint(user.getPoint() + 5); - Point newPoint=Point.builder() + Point newPoint = Point.builder() .amount(5) - .content("게이지 투표에 대한 "+5+" 포인트 획득") + .content("게이지 투표에 대한 " + 5 + " 포인트 획득") .build(); newPoint.setUser(user); pointRepository.save(newPoint); - Integer value=request.getValue(); + Integer value = request.getValue(); gaugePollRepository.findById(PostId); - Optional optionalPost=postRepository.findById(PostId); - Post gaugePost=optionalPost.get(); - Integer currentGauge=gaugePost.getGaugePoll().getGauge(); - Integer engagedUser=gaugePost.getGaugePoll().getGaugeVoteList().size(); - int result1=(int)Math.round((currentGauge*(engagedUser-1.0)+value)/(engagedUser)); - Integer result=(Integer)result1; + Optional optionalPost = postRepository.findById(PostId); + Post gaugePost = optionalPost.get(); + Integer currentGauge = gaugePost.getGaugePoll().getGauge(); + Integer engagedUser = gaugePost.getGaugePoll().getGaugeVoteList().size(); + int result1 = (int) Math.round((currentGauge * (engagedUser - 1.0) + value) / (engagedUser)); + Integer result = (Integer) result1; gaugePost.getGaugePoll().setGauge(result); return gaugeVoteRepository.save(newGaugeVote); } + @Override @Transactional - public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request,Long PostId, Long userId){ + public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request, Long PostId, Long userId) { Card_vote newCardVote = VoteConverter.toCardVote(request); User user = userRepository.findById(userId) .orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); newCardVote.setUser(user); - Post post=postRepository.findById(PostId) - .orElseThrow(()-> new GeneralException(ErrorStatus.POST_NOT_FOUND)); - if(post.getCardPoll().getCardVoteList().stream().anyMatch(cardVote -> cardVote.getUser().getId().equals(userId))){ + Post post = postRepository.findById(PostId) + .orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + if (post.getCardPoll().getCardVoteList().stream().anyMatch(cardVote -> cardVote.getUser().getId().equals(userId))) { throw new GeneralException(ErrorStatus.ALREADY_VOTE); } - Card_poll cardPoll=post.getCardPoll(); + Card_poll cardPoll = post.getCardPoll(); newCardVote.setCardPoll(cardPoll); List selectedCandidateIds = request.getSelectList(); @@ -157,14 +158,14 @@ public Card_vote castCardVote(VoteRequestDTO.CardVoteRequestDTO request,Long Pos LocalDateTime now = LocalDateTime.now(); long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getCardPoll().getDeadline()); Boolean voteOnGoing = nanosUntilDeadline > 0; - if(!voteOnGoing){ + if (!voteOnGoing) { throw new GeneralException(ErrorStatus.DEADLINE_OVER); } user.setPoint(user.getPoint() + 5); - Point newPoint=Point.builder() + Point newPoint = Point.builder() .amount(5) - .content("카드 투표에 대한 "+5+" 포인트 획득") + .content("카드 투표에 대한 " + 5 + " 포인트 획득") .build(); newPoint.setUser(user); pointRepository.save(newPoint); diff --git a/src/main/java/friend/spring/validation/annotation/ContentTextLimit.java b/src/main/java/friend/spring/validation/annotation/ContentTextLimit.java index 1eb36e2..6b750c1 100644 --- a/src/main/java/friend/spring/validation/annotation/ContentTextLimit.java +++ b/src/main/java/friend/spring/validation/annotation/ContentTextLimit.java @@ -8,10 +8,12 @@ @Documented @Constraint(validatedBy = ContentTextLimitValidator.class) -@Target( { ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface ContentTextLimit { String message() default "최소 5자 이상, 1000자 미만 입력해 주세요."; + Class[] groups() default {}; + Class[] payload() default {}; } diff --git a/src/main/java/friend/spring/validation/annotation/TitleTextLimit.java b/src/main/java/friend/spring/validation/annotation/TitleTextLimit.java index 6065ff1..895eff9 100644 --- a/src/main/java/friend/spring/validation/annotation/TitleTextLimit.java +++ b/src/main/java/friend/spring/validation/annotation/TitleTextLimit.java @@ -8,10 +8,12 @@ @Documented @Constraint(validatedBy = TitleTextLimitValidator.class) -@Target( { ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface TitleTextLimit { String message() default "최소 5자 이상, 30자 미만 입력해 주세요."; + Class[] groups() default {}; + Class[] payload() default {}; } diff --git a/src/main/java/friend/spring/validation/validator/ContentTextLimitValidator.java b/src/main/java/friend/spring/validation/validator/ContentTextLimitValidator.java index 44a2515..2acfae5 100644 --- a/src/main/java/friend/spring/validation/validator/ContentTextLimitValidator.java +++ b/src/main/java/friend/spring/validation/validator/ContentTextLimitValidator.java @@ -10,7 +10,7 @@ @Component @RequiredArgsConstructor -public class ContentTextLimitValidator implements ConstraintValidator { +public class ContentTextLimitValidator implements ConstraintValidator { @Override public void initialize(ContentTextLimit constraintAnnotation) { ConstraintValidator.super.initialize(constraintAnnotation); @@ -18,8 +18,8 @@ public void initialize(ContentTextLimit constraintAnnotation) { @Override public boolean isValid(String value, ConstraintValidatorContext context) { - boolean isValid= value.length() >= 5 && value.length() < 1000; - if(!isValid){ + boolean isValid = value.length() >= 5 && value.length() < 1000; + if (!isValid) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate(ErrorStatus.CONTENT_TEXT_LIMIT.getMessage()).addConstraintViolation(); } diff --git a/src/main/java/friend/spring/validation/validator/DeadlineLimitValidator.java b/src/main/java/friend/spring/validation/validator/DeadlineLimitValidator.java index cdc00e5..031abfd 100644 --- a/src/main/java/friend/spring/validation/validator/DeadlineLimitValidator.java +++ b/src/main/java/friend/spring/validation/validator/DeadlineLimitValidator.java @@ -22,7 +22,7 @@ public boolean isValid(LocalDateTime deadline, ConstraintValidatorContext contex long daysUntilDeadline = ChronoUnit.DAYS.between(now, deadline); boolean isValid = minutesUntilDeadline >= 1 && daysUntilDeadline <= 30; - if(!isValid){ + if (!isValid) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate(ErrorStatus.DEADLINE_LIMIT.getMessage()).addConstraintViolation(); } diff --git a/src/main/java/friend/spring/validation/validator/TitleTextLimitValidator.java b/src/main/java/friend/spring/validation/validator/TitleTextLimitValidator.java index d4ab8ab..81e99da 100644 --- a/src/main/java/friend/spring/validation/validator/TitleTextLimitValidator.java +++ b/src/main/java/friend/spring/validation/validator/TitleTextLimitValidator.java @@ -10,7 +10,7 @@ @Component @RequiredArgsConstructor -public class TitleTextLimitValidator implements ConstraintValidator { +public class TitleTextLimitValidator implements ConstraintValidator { @Override public void initialize(TitleTextLimit constraintAnnotation) { @@ -19,8 +19,8 @@ public void initialize(TitleTextLimit constraintAnnotation) { @Override public boolean isValid(String value, ConstraintValidatorContext context) { - boolean isValid= value.length() >= 5 && value.length() < 30; - if(!isValid){ + boolean isValid = value.length() >= 5 && value.length() < 30; + if (!isValid) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate(ErrorStatus.TITLE_TEXT_LIMIT.getMessage()).addConstraintViolation(); } diff --git a/src/main/java/friend/spring/web/controller/AlarmRestController.java b/src/main/java/friend/spring/web/controller/AlarmRestController.java index 6cc6229..ab0517b 100644 --- a/src/main/java/friend/spring/web/controller/AlarmRestController.java +++ b/src/main/java/friend/spring/web/controller/AlarmRestController.java @@ -25,12 +25,13 @@ public class AlarmRestController { private final AlarmService alarmService; private final JwtTokenService jwtTokenService; + //알림 조회 @GetMapping("/alarm") - @Operation(summary = "사용자 알림 조회 API",description = "사용자의 알림 목록을 조회하는 API이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요") + @Operation(summary = "사용자 알림 조회 API", description = "사용자의 알림 목록을 조회하는 API이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "ALARM4001",description = "NOT_FOUND, 알림을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "ALARM4001", description = "NOT_FOUND, 알림을 찾을 수 없습니다."), }) @Parameters({ @@ -39,32 +40,32 @@ public class AlarmRestController { private ApiResponse getAlarm( @RequestHeader(name = "atk") String atk, HttpServletRequest request, - @RequestParam(name = "page") Integer page){ - Long userId=jwtTokenService.JwtToId(request); + @RequestParam(name = "page") Integer page) { + Long userId = jwtTokenService.JwtToId(request); Page alarmList = alarmService.getAlarmList(userId, page); return ApiResponse.onSuccess(AlarmConverter.toAlarmListResDTO(alarmList)); } // 홈 - 안 읽은 알림 존재 여부 조회 @GetMapping("/alarm/notReadAlarm") - @Operation(summary = "홈 - 안 읽은 알림 존재 여부 조회 API",description = "사용자가 안 읽은 알림이 존재하는지 여부를 조회하는 API입니다.") + @Operation(summary = "홈 - 안 읽은 알림 존재 여부 조회 API", description = "사용자가 안 읽은 알림이 존재하는지 여부를 조회하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공") + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공") }) @Parameters({}) private ApiResponse getRemainingAlarm( @RequestHeader(name = "atk") String atk, HttpServletRequest request - ){ + ) { return ApiResponse.onSuccess(alarmService.getRemainingAlarm(request)); } // 알림 읽음 처리 @PatchMapping("/alarm/{alarm-id}") - @Operation(summary = "사용자 알림 읽음 처리 API",description = "사용자의 알림을 읽음 처리하는 API입니다.") + @Operation(summary = "사용자 알림 읽음 처리 API", description = "사용자의 알림을 읽음 처리하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "ALARM4001",description = "NOT_FOUND, 알림을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "ALARM4001", description = "NOT_FOUND, 알림을 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "alarm-id", description = "path variable - 알람 아이디"), @@ -73,7 +74,7 @@ private ApiResponse editAlarmRead( @PathVariable("alarm-id") Long alarmId, @RequestHeader(name = "atk") String atk, HttpServletRequest request - ){ + ) { alarmService.editAlarmRead(alarmId, request); return ApiResponse.onSuccess(null); } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 8f23ed3..583516c 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -34,10 +34,10 @@ public class CommentRestController { @PostMapping("/{post-id}/comment") @Operation(summary = "댓글 작성 API", description = "댓글 작성하는 API입니다. ex) /posts/1/comment") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, (부모 루트) 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001", description = "NOT_FOUND, (부모 루트) 댓글을 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @@ -57,10 +57,10 @@ public ApiResponse createComment( @PostMapping("/{post-id}/comment/{comment-id}/like") @Operation(summary = "댓글 추천(좋아요) 생성 API", description = "댓글 추천(좋아요) 생성하는 API입니다. ex) /posts/1/comment/1/like") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001", description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @@ -81,11 +81,11 @@ public ApiResponse likeComment( @DeleteMapping("/{post-id}/comment/{comment-id}/like/del") @Operation(summary = "댓글 추천(좋아요) 해제 API", description = "댓글 추천(좋아요) 해제하는 API입니다. ex) /posts/1/comment/1/like/del") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4002",description = "NOT_FOUND, 댓글에 대한 좋아요 데이터를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001", description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4002", description = "NOT_FOUND, 댓글에 대한 좋아요 데이터를 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @@ -106,8 +106,8 @@ public ApiResponse dislikeComment( @GetMapping("/{post-id}/comments") @Operation(summary = "댓글 조회 API", description = "댓글을 조회하는 API입니다. ex) /posts/111/comments") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디") @@ -124,13 +124,13 @@ public ApiResponse> getComments( @PostMapping("/{post-id}/comment/{comment-id}/choice") @Operation(summary = "댓글 채택 API", description = "댓글 채택 데이터를 생성하는 API입니다. ex) /posts/1/comment/1/choice") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4002",description = "BAD_REQUEST, 올바른 사용자(글 작성자)가 아닙니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4003",description = "BAD_REQUEST, 댓글 채택은 1개 댓글에 대해서만 가능합니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4004",description = "BAD_REQUEST, 자기 자신은 채택할 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4002", description = "BAD_REQUEST, 올바른 사용자(글 작성자)가 아닙니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001", description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4003", description = "BAD_REQUEST, 댓글 채택은 1개 댓글에 대해서만 가능합니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4004", description = "BAD_REQUEST, 자기 자신은 채택할 수 없습니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @@ -151,11 +151,11 @@ public ApiResponse selectComment( @PatchMapping("/{post-id}/comment/{comment-id}/edit") @Operation(summary = "댓글 수정 API", description = "댓글 수정하는 API입니다. ex) /posts/1/comment/1/edit") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4005",description = "올바른 사용자(댓글 작성자)가 아닙니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001", description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4005", description = "올바른 사용자(댓글 작성자)가 아닙니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @@ -177,11 +177,11 @@ public ApiResponse editComment( @PatchMapping("/{post-id}/comment/{comment-id}/del") @Operation(summary = "댓글 삭제 API", description = "댓글 삭제하는 API입니다. ex) /posts/1/comment/1/del") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4005",description = "올바른 사용자(댓글 작성자)가 아닙니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001", description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4005", description = "올바른 사용자(댓글 작성자)가 아닙니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), diff --git a/src/main/java/friend/spring/web/controller/MyPageRestController.java b/src/main/java/friend/spring/web/controller/MyPageRestController.java index c5dd862..0f58343 100644 --- a/src/main/java/friend/spring/web/controller/MyPageRestController.java +++ b/src/main/java/friend/spring/web/controller/MyPageRestController.java @@ -36,11 +36,11 @@ public class MyPageRestController { //저장한 게시물(내 카테고리) 조회 @GetMapping("/post") - @Operation(summary = "사용자 글 카테고리 조회 API",description = "사용자의 저장 글 카테고리 목록을 집합으로 조회하는 API입니다.") + @Operation(summary = "사용자 글 카테고리 조회 API", description = "사용자의 저장 글 카테고리 목록을 집합으로 조회하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "회원정보가 존재하지 않습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004",description = "카테고리를 찾을 수 없습니다.") + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "회원정보가 존재하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004", description = "카테고리를 찾을 수 없습니다.") }) @Parameters({ @@ -48,7 +48,7 @@ public class MyPageRestController { }) public ApiResponse getCategorySet( @RequestHeader(name = "atk") String atk, - HttpServletRequest request){ + HttpServletRequest request) { Long userId = jwtTokenService.JwtToId(request); List categoryList = myPageService.getCategoryList(userId); return ApiResponse.onSuccess(MyPageConverter.toSavedCategoryResDTO(categoryList)); @@ -56,12 +56,12 @@ public ApiResponse getCategorySet( //저장한 게시물(모든게시물) @GetMapping("/post/all") - @Operation(summary = "저장한 게시물(모든게시물) 조회 API",description = "사용자의 전체 저장 글을 조회하는 API입니다.") + @Operation(summary = "저장한 게시물(모든게시물) 조회 API", description = "사용자의 전체 저장 글을 조회하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "회원정보가 존재하지 않습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "글을 찾을 수 없습니다.."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4005",description = "저장한 글이 없습니다.") + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "회원정보가 존재하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "글을 찾을 수 없습니다.."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4005", description = "저장한 글이 없습니다.") }) @Parameters({ @@ -74,7 +74,7 @@ public ApiResponse getAllSavedPosts( @RequestParam(name = "page", defaultValue = "0") Integer page, @RequestParam(name = "sort", defaultValue = "0") Integer sort, @RequestHeader(name = "atk") String atk, - HttpServletRequest request){ + HttpServletRequest request) { Long userId = jwtTokenService.JwtToId(request); Page allPostList = myPageService.getAllPostList(userId, page, sort); return ApiResponse.onSuccess(MyPageConverter.toSavedAllPostResDTO(allPostList)); @@ -84,8 +84,8 @@ public ApiResponse getAllSavedPosts( @PatchMapping(value = "/profile/modify/image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @Operation(summary = "회원정보 사용자 프로필 사진 수정 API", description = "사용자 프로필 사진을 수정하는 API입니다. ex) /user/my-page/profile/modify/image") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @@ -103,8 +103,8 @@ public ApiResponse editUserImage( @GetMapping(value = "/profile/modify") @Operation(summary = "회원정보 수정 페이지 API", description = "회원정보 수정 페이지를 조회하는 API입니다. ex) /user/my-page/profile/modify") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @@ -122,7 +122,7 @@ public ApiResponse getEditUserPage( @Operation(summary = "회원정보 이름 수정 API", description = "회원정보 이름을 수정하는 API입니다. ex) /user/my-page/profile/modify/name") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005",description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005", description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), }) @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") @@ -130,7 +130,7 @@ public ApiResponse getEditUserPage( public ApiResponse editUserName( @RequestHeader(name = "atk") String atk, HttpServletRequest request, - @RequestBody @Valid MyPageRequestDTO.ProfileEditNameReq profileEditNameReq){ + @RequestBody @Valid MyPageRequestDTO.ProfileEditNameReq profileEditNameReq) { Long userId = jwtTokenService.JwtToId(request); emailService.CheckAuthNum(profileEditNameReq.getEmail(), profileEditNameReq.getCertification()); User editUserName = myPageService.editUserName(userId, profileEditNameReq); @@ -141,7 +141,7 @@ public ApiResponse editUserName( @Operation(summary = "회원정보 이메일 수정 API", description = "회원정보 이메일을 수정하는 API입니다. ex) /user/my-page/profile/modify/email") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005",description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005", description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), }) @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") @@ -149,7 +149,7 @@ public ApiResponse editUserName( public ApiResponse editUserEmail( @RequestHeader(name = "atk") String atk, HttpServletRequest request, - @RequestBody @Valid MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq){ + @RequestBody @Valid MyPageRequestDTO.ProfileEditEmailReq profileEditEmailReq) { Long userId = jwtTokenService.JwtToId(request); emailService.CheckAuthNum(profileEditEmailReq.getCurEmail(), profileEditEmailReq.getCertification()); User editUserEmail = myPageService.editUserEmail(userId, profileEditEmailReq); @@ -160,7 +160,7 @@ public ApiResponse editUserEmail( @Operation(summary = "회원정보 번호 수정 API", description = "회원정보 번호를 수정하는 API입니다. ex) /user/my-page/profile/modify/phone") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005",description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005", description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), }) @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") @@ -168,7 +168,7 @@ public ApiResponse editUserEmail( public ApiResponse editUserPhone( @RequestHeader(name = "atk") String atk, HttpServletRequest request, - @RequestBody @Valid MyPageRequestDTO.ProfileEditPhoneReq profileEditPhoneReq){ + @RequestBody @Valid MyPageRequestDTO.ProfileEditPhoneReq profileEditPhoneReq) { Long userId = jwtTokenService.JwtToId(request); emailService.CheckAuthNum(profileEditPhoneReq.getEmail(), profileEditPhoneReq.getCertification()); User editUserPhone = myPageService.editUserPhone(userId, profileEditPhoneReq); @@ -179,8 +179,8 @@ public ApiResponse editUserPhone( @Operation(summary = "회원정보 비밀번호 수정 API", description = "회원정보 비밀번호를 수정하는 API입니다. ex) /user/my-page/profile/modify/password") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4008",description = "NOT_FOUND, 비밀번호가 틀렸습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4009",description = "NOT_FOUND, 확인 비밀번호가 일치하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4008", description = "NOT_FOUND, 비밀번호가 틀렸습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4009", description = "NOT_FOUND, 확인 비밀번호가 일치하지 않습니다."), }) @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") @@ -188,7 +188,7 @@ public ApiResponse editUserPhone( public ApiResponse editUserPassword( @RequestHeader(name = "atk") String atk, HttpServletRequest request, - @RequestBody @Valid MyPageRequestDTO.ProfileEditPasswordReq profileEditPasswordReq){ + @RequestBody @Valid MyPageRequestDTO.ProfileEditPasswordReq profileEditPasswordReq) { Long userId = jwtTokenService.JwtToId(request); User editUserPassword = myPageService.editUserPassword(userId, profileEditPasswordReq); return ApiResponse.onSuccess(MyPageConverter.toProfileEditPasswordResDTO(editUserPassword)); @@ -206,7 +206,7 @@ public ApiResponse editUserPassword( public ApiResponse editUserSecurity( @RequestHeader(name = "atk") String atk, HttpServletRequest request, - @RequestBody @Valid MyPageRequestDTO.ProfileEditSecurityReq profileEditSecurityReq){ + @RequestBody @Valid MyPageRequestDTO.ProfileEditSecurityReq profileEditSecurityReq) { Long userId = jwtTokenService.JwtToId(request); emailService.CheckAuthNum(profileEditSecurityReq.getCurEmail(), profileEditSecurityReq.getCertification()); emailService.CheckAuthNum(profileEditSecurityReq.getChangeEmail(), profileEditSecurityReq.getNxtCertification()); @@ -227,7 +227,7 @@ public ApiResponse editUserSecurity( public ApiResponse editUserSecurity( @RequestHeader(name = "atk") String atk, HttpServletRequest request, - @RequestBody @Valid MyPageRequestDTO.MyInquiryReq myInquiryReq){ + @RequestBody @Valid MyPageRequestDTO.MyInquiryReq myInquiryReq) { Long userId = jwtTokenService.JwtToId(request); Inquiry inquiry = myPageService.createInquiry(userId, myInquiryReq); return ApiResponse.onSuccess(MyPageConverter.toMyInquiryRes(inquiry)); @@ -237,8 +237,8 @@ public ApiResponse editUserSecurity( @Operation(summary = "사용자 글 카테고리 상세보기 조회 API", description = "카테고리별로 상세화면을 조회하는 API입니다. ex) /user/my-page/post/{category-id}") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004",description = "NOT_FOUND, 글에 대한 스크랩 데이터를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004", description = "NOT_FOUND, 글에 대한 스크랩 데이터를 찾을 수 없습니다."), }) @Parameters({ @@ -250,7 +250,7 @@ public ApiResponse GetUserCate @RequestHeader(name = "atk") String atk, @PathVariable("category-id") Long categoryId, @RequestParam(name = "page", defaultValue = "0") Integer page, - HttpServletRequest request){ + HttpServletRequest request) { Long userId = jwtTokenService.JwtToId(request); Page categoryDetailList = myPageService.getCategoryDetailList(userId, categoryId, page); Category category = myPageService.getCategory(categoryId); @@ -261,13 +261,13 @@ public ApiResponse GetUserCate @Operation(summary = "공지사항 리스트 조회 API", description = "전체 공지사항의 리스트를 조회하는 API입니다. ex) /user/my-page/setting/notice") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "NOTICE4001",description = "NOT_FOUND, 공지사항이 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "NOTICE4001", description = "NOT_FOUND, 공지사항이 없습니다."), }) @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), }) public ApiResponse getNoticeList( - @RequestParam(name = "page", defaultValue = "0") Integer page){ + @RequestParam(name = "page", defaultValue = "0") Integer page) { Page noticeList = myPageService.getNoticeList(30L, page); return ApiResponse.onSuccess(MyPageConverter.toNoticeListRes(noticeList)); } @@ -276,14 +276,14 @@ public ApiResponse getNoticeList( @Operation(summary = "공지사항 상세 조회 API", description = "전체 공지사항 상세내용을 조회하는 API입니다. ex) /user/my-page/setting/notice/{notice-id}") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다. "), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "NOTICE4001",description = "NOT_FOUND, 공지사항이 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "NOTICE4001", description = "NOT_FOUND, 공지사항이 없습니다."), }) @Parameters({ @Parameter(name = "notice-id", description = "path variable - 공지사항 아이디"), }) public ApiResponse getNoticeDetail( @PathVariable("notice-id") Long noticeId - ){ + ) { Notice noticeDetail = myPageService.getNoticeDetail(noticeId); return ApiResponse.onSuccess(MyPageConverter.toNoticeDetailRes(noticeDetail)); } @@ -296,7 +296,7 @@ public ApiResponse getNoticeDetail( @Parameters({ }) public ApiResponse getTerm( - ){ + ) { Term term = myPageService.getTerm(30L); return ApiResponse.onSuccess(MyPageConverter.toTermRes(term)); } @@ -309,7 +309,7 @@ public ApiResponse getTerm( @Parameters({ }) public ApiResponse getPrivacy( - ){ + ) { Term term = myPageService.getPrivacy(30L); return ApiResponse.onSuccess(MyPageConverter.toPrivacyRes(term)); } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index abd4319..c8ce789 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -1,4 +1,5 @@ package friend.spring.web.controller; + import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.CandidateConverter; import friend.spring.converter.PostConverter; @@ -34,27 +35,28 @@ public class PostRestController { private final PostQueryService postQueryService; private final PostRepository postRepository; private final JwtTokenService jwtTokenService; + @PostMapping(value = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @Operation(summary = "글 작성 API", description = "글을 추가 합니다.") @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), - @Parameter(name="title", description=" 글 제목"), - @Parameter(name="content", description=" 글 내용"), - @Parameter(name="category", description="카테고리. 한글 입력(ex 교육)" ), - @Parameter(name="postType", description=" 글 종류
1 : VOTE
2 : REVIEW"), - @Parameter(name="postVoteType", description=" 투표 종류
1 : GENERAL
2 : GAUGE
3 : CARD
해당 사항 없을시 null"), - @Parameter(name="pollTitle", description=" 투표 제목"), - @Parameter(name="multipleChoice", description=" 복수 선택 여부"), - @Parameter(name="parent_id", description=" 원글(후기글 경우) id
해당 사항 없을시 null"), - @Parameter(name="deadline", description=" 투표 마감 시간
해당 사항 없을시 null(기본값 1시간 이후)"), - @Parameter(name="point", description=" 포인트
해당 사항 없을시 null") + @Parameter(name = "title", description = " 글 제목"), + @Parameter(name = "content", description = " 글 내용"), + @Parameter(name = "category", description = "카테고리. 한글 입력(ex 교육)"), + @Parameter(name = "postType", description = " 글 종류
1 : VOTE
2 : REVIEW"), + @Parameter(name = "postVoteType", description = " 투표 종류
1 : GENERAL
2 : GAUGE
3 : CARD
해당 사항 없을시 null"), + @Parameter(name = "pollTitle", description = " 투표 제목"), + @Parameter(name = "multipleChoice", description = " 복수 선택 여부"), + @Parameter(name = "parent_id", description = " 원글(후기글 경우) id
해당 사항 없을시 null"), + @Parameter(name = "deadline", description = " 투표 마감 시간
해당 사항 없을시 null(기본값 1시간 이후)"), + @Parameter(name = "point", description = " 포인트
해당 사항 없을시 null") }) public ApiResponse join(@RequestPart(value = "request") @Valid PostRequestDTO.AddPostDTO request, // @RequestPart(value = "file", required = false) List file, @RequestHeader("atk") String atk, - HttpServletRequest request2){ - Post post= postService.joinPost(request,request2); + HttpServletRequest request2) { + Post post = postService.joinPost(request, request2); return ApiResponse.onSuccess(PostConverter.toAddPostResultDTO(post)); } @@ -62,10 +64,10 @@ public ApiResponse join(@RequestPart(value = " @Operation(summary = "후보 생성 API", description = "후보를 생성합니다.(글 작성 API 호출 후 postId 응답 받으시면, 후보 개수 만큼 바로 호출해주세요!)") @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), - @Parameter(name="pollOption", description=" 투표 후보{optionString : string, optionImg : MultipartFile}
해당 사항 없을시 null"), + @Parameter(name = "pollOption", description = " 투표 후보{optionString : string, optionImg : MultipartFile}
해당 사항 없을시 null"), }) public ApiResponse createCandidate( - @PathVariable(name="post-id") Long postId, + @PathVariable(name = "post-id") Long postId, @RequestBody CandidateRequestDTO.AddCandidateRequestDTO request, @RequestHeader("atk") String atk, HttpServletRequest request2) throws IOException { @@ -82,30 +84,32 @@ public ApiResponse createCandidate( @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse getParentPosts(@RequestParam(name = "page", defaultValue = "0") Integer page, - @RequestParam(name = "size",defaultValue = "15") Integer size, + @RequestParam(name = "size", defaultValue = "15") Integer size, @RequestHeader("atk") String atk, - HttpServletRequest request2){ - Page postPage=postQueryService.getParentPostList(page,size,request2); - Long userId=jwtTokenService.JwtToId(request2); - return ApiResponse.onSuccess(PostConverter.parentPostGetListDTO(postPage,userId)); + HttpServletRequest request2) { + Page postPage = postQueryService.getParentPostList(page, size, request2); + Long userId = jwtTokenService.JwtToId(request2); + return ApiResponse.onSuccess(PostConverter.parentPostGetListDTO(postPage, userId)); } + @GetMapping("/{post-id}") @Operation(summary = "글 상세 보기 API", description = "글 상세 보기합니다
response로 나오는 isLike, isComment는 각각 조회하는 사용자의 좋아요 클릭 여부, " + "댓글 작성 여부입니다..") @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) - public ApiResponse getPostDetail(@PathVariable(name="post-id")Long PostId, + public ApiResponse getPostDetail(@PathVariable(name = "post-id") Long PostId, @RequestHeader("atk") String atk, - HttpServletRequest request2){ - Long userId=jwtTokenService.JwtToId(request2); - Post post =postQueryService.getPostDetail(PostId); - Post parentPost=postQueryService.ParentPost(PostId);; - Boolean engage=postQueryService.checkEngage(PostId,userId); - return ApiResponse.onSuccess(PostConverter.postDetailResponse(post,engage,userId,parentPost)); + HttpServletRequest request2) { + Long userId = jwtTokenService.JwtToId(request2); + Post post = postQueryService.getPostDetail(PostId); + Post parentPost = postQueryService.ParentPost(PostId); + Boolean engage = postQueryService.checkEngage(PostId, userId); + return ApiResponse.onSuccess(PostConverter.postDetailResponse(post, engage, userId, parentPost)); } + @GetMapping("/poll-post/{category}") @Operation(summary = "고민글 전체 보기 API", description = "고민글 전체 보기합니다") @Parameters({ @@ -115,13 +119,13 @@ public ApiResponse getPostDetail(@PathVariab @Parameter(name = "category", description = "path variable - category(한글). 모두 보기는 '모두'라고 입력 하시면 됩니다.") }) public ApiResponse getPostAll(@RequestParam(name = "page", defaultValue = "0") Integer page, - @RequestParam(name = "size",defaultValue = "15") Integer size, - @PathVariable(name = "category") String category, - @RequestHeader("atk") String atk, - HttpServletRequest request2){ - Long userId=jwtTokenService.JwtToId(request2); - Page postPage=postQueryService.getPostList(page,size,category); - return ApiResponse.onSuccess(PostConverter.pollPostGetListDTO(postPage,userId)); + @RequestParam(name = "size", defaultValue = "15") Integer size, + @PathVariable(name = "category") String category, + @RequestHeader("atk") String atk, + HttpServletRequest request2) { + Long userId = jwtTokenService.JwtToId(request2); + Page postPage = postQueryService.getPostList(page, size, category); + return ApiResponse.onSuccess(PostConverter.pollPostGetListDTO(postPage, userId)); } @@ -133,14 +137,14 @@ public ApiResponse getPostAll(@RequestParam( @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정) 디폴트값 15"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) - public ApiResponse getReviewAll(@RequestParam(name="arrange", defaultValue = "0") Integer arrange, - @RequestParam(name = "page", defaultValue = "0") Integer page, - @RequestParam(name = "size",defaultValue = "15") Integer size, - @RequestHeader("atk") String atk, - HttpServletRequest request2){ - Long userId=jwtTokenService.JwtToId(request2); - Page postPage=postQueryService.getReviewList(page,size,arrange); - return ApiResponse.onSuccess(PostConverter.reviewPostGetListDTO(postPage,userId)); + public ApiResponse getReviewAll(@RequestParam(name = "arrange", defaultValue = "0") Integer arrange, + @RequestParam(name = "page", defaultValue = "0") Integer page, + @RequestParam(name = "size", defaultValue = "15") Integer size, + @RequestHeader("atk") String atk, + HttpServletRequest request2) { + Long userId = jwtTokenService.JwtToId(request2); + Page postPage = postQueryService.getReviewList(page, size, arrange); + return ApiResponse.onSuccess(PostConverter.reviewPostGetListDTO(postPage, userId)); } @PatchMapping("/{post-id}/edit") @@ -153,7 +157,7 @@ public ApiResponse editPost(@PathVariable("post-id") Long postId, @RequestBody @Valid PostRequestDTO.PostEditReq request, @RequestHeader("atk") String atk, HttpServletRequest request2) { - Long userId=jwtTokenService.JwtToId(request2); + Long userId = jwtTokenService.JwtToId(request2); postService.editPost(postId, request, userId); return ApiResponse.onSuccess(null); } @@ -169,7 +173,7 @@ public ApiResponse deleteComment( @RequestHeader("atk") String atk, HttpServletRequest request2 ) { - Long userId=jwtTokenService.JwtToId(request2); + Long userId = jwtTokenService.JwtToId(request2); postService.deletePost(postId, userId); return ApiResponse.onSuccess(null); } @@ -178,9 +182,9 @@ public ApiResponse deleteComment( @PostMapping("/{post-id}/like") @Operation(summary = "글 추천(좋아요) 생성 API", description = "글 추천(좋아요) 생성하는 API입니다. ex) /posts/1/like") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @@ -199,10 +203,10 @@ public ApiResponse likePost( @DeleteMapping("/{post-id}/like/del") @Operation(summary = "글 추천(좋아요) 해제 API", description = "글 추천(좋아요) 해제하는 API입니다. ex) /posts/1/like/del") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4003",description = "글에 대한 좋아요 데이터를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4003", description = "글에 대한 좋아요 데이터를 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @@ -221,7 +225,7 @@ public ApiResponse dislikePost( @GetMapping("/best") @Operation(summary = "홈 - 지금 가장 핫한 고민투표 API", description = "홈 - 지금 가장 핫한 고민투표 조회 API입니다. ex) /posts/best") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), }) @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), @@ -241,7 +245,7 @@ public ApiResponse getBestPosts( @GetMapping("/recent") @Operation(summary = "홈 - 답변을 기다리는 고민들 API", description = "홈 - 답변을 기다리는 고민들 조회 API입니다. ex) /posts/recent") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), }) @Parameters({ @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 (0부터 시작)"), @@ -261,9 +265,9 @@ public ApiResponse getRecentPosts( @PostMapping("/{post-id}/scrap") @Operation(summary = "글 스크랩 추가 API", description = "글 스크랩 추가하는 API입니다. ex) /posts/1/scrap") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), @@ -282,10 +286,10 @@ public ApiResponse createScrapPost( @DeleteMapping("/{post-id}/scrap/del") @Operation(summary = "글 스크랩 해제 API", description = "글 스크랩 해제하는 API입니다. ex) /posts/1/scrap/del") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 요청에 성공했습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004",description = "글에 대한 스크랩 데이터를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4004", description = "글에 대한 스크랩 데이터를 찾을 수 없습니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), diff --git a/src/main/java/friend/spring/web/controller/RootController.java b/src/main/java/friend/spring/web/controller/RootController.java index 7293285..f15b1a7 100644 --- a/src/main/java/friend/spring/web/controller/RootController.java +++ b/src/main/java/friend/spring/web/controller/RootController.java @@ -10,5 +10,4 @@ public String healthCheck() { return "I'm healthy!"; } - } diff --git a/src/main/java/friend/spring/web/controller/SseController.java b/src/main/java/friend/spring/web/controller/SseController.java index a0f8f4d..3737ce8 100644 --- a/src/main/java/friend/spring/web/controller/SseController.java +++ b/src/main/java/friend/spring/web/controller/SseController.java @@ -16,8 +16,8 @@ public class SseController { @GetMapping(value = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter subscribe( - @RequestHeader(name = "atk") String atk, - HttpServletRequest request + @RequestHeader(name = "atk") String atk, + HttpServletRequest request ) { return notificationService.subscribe(request); } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 91f3fd3..df72b7a 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -41,48 +41,49 @@ public class UserRestController { private final CommentService commentService; private final JwtTokenService jwtTokenService; private final AuthService authService; - + //마이 페이지 조회 @GetMapping("/my-page") public ApiResponse getMyPage( @RequestHeader(name = "atk") String atk, HttpServletRequest request) { - Long userId=jwtTokenService.JwtToId(request); + Long userId = jwtTokenService.JwtToId(request); User myPage = userService.findMyPage(userId); return ApiResponse.onSuccess(UserConverter.toMypageResDTO(myPage)); } - @PostMapping ("/mailSend")//이메일 인증 코드 전송 - @Operation(summary = "이메일 인증 코드 전송 API",description = "이메일 인증 코드 전송하는 API입니다.") + @PostMapping("/mailSend")//이메일 인증 코드 전송 + @Operation(summary = "이메일 인증 코드 전송 API", description = "이메일 인증 코드 전송하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), }) - @Parameters({ }) - public ApiResponse mailSend(@RequestBody @Valid UserRequestDTO.EmailSendReq emailDto){ + @Parameters({}) + public ApiResponse mailSend(@RequestBody @Valid UserRequestDTO.EmailSendReq emailDto) { System.out.println("이메일 인증 요청이 들어옴"); - System.out.println("이메일 인증 이메일 :"+emailDto.getEmail()); + System.out.println("이메일 인증 이메일 :" + emailDto.getEmail()); String code = mailService.joinEmail(emailDto.getEmail()); return ApiResponse.onSuccess(UserConverter.toEmailSendRes(code)); } + @PostMapping("/mailauthCheck")//이메일 코드 확인 - @Operation(summary = "이메일 코드 확인 API",description = "이메일 코드 확인하는 API입니다.") + @Operation(summary = "이메일 코드 확인 API", description = "이메일 코드 확인하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005",description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005", description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), }) - @Parameters({ }) - public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailSendCheckReq emailSendCheckReq){ + @Parameters({}) + public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailSendCheckReq emailSendCheckReq) { mailService.CheckAuthNum(emailSendCheckReq.getEmail(), emailSendCheckReq.getAuthNum()); return ApiResponse.onSuccess(null); } //나의 Q&A 질문 조회 @GetMapping("/my-page/profile/question") - @Operation(summary = "나의 Q&A 질문 조회 API",description = "사용자의 나의 Q&A 질문 조회 API 이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요") + @Operation(summary = "나의 Q&A 질문 조회 API", description = "사용자의 나의 Q&A 질문 조회 API 이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001",description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), }) @Parameters({ @@ -92,8 +93,8 @@ public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.EmailS public ApiResponse getQuestion( @RequestHeader(name = "atk") String atk, HttpServletRequest request, - @RequestParam(name = "page") Integer page){ - Long userId=jwtTokenService.JwtToId(request); + @RequestParam(name = "page") Integer page) { + Long userId = jwtTokenService.JwtToId(request); User myPage = userService.findMyPage(userId); Level nxtLevel = userService.nextLevel(userId); Page myPostList = postService.getMyPostList(userId, page); @@ -103,10 +104,10 @@ public ApiResponse getQuestion( //나의 Q&A 답변 조회 @GetMapping("/my-page/profile/answer") - @Operation(summary = "나의 Q&A 답변 조회 API",description = "사용자의 Q&A 답변 조회 API 이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요") + @Operation(summary = "나의 Q&A 답변 조회 API", description = "사용자의 Q&A 답변 조회 API 이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001",description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4001", description = "NOT_FOUND, 댓글을 찾을 수 없습니다."), }) @Parameters({ @@ -116,71 +117,74 @@ public ApiResponse getQuestion( public ApiResponse getAnswer( @RequestHeader(name = "atk") String atk, HttpServletRequest request, - @RequestParam(name = "page") Integer page){ - Long userId=jwtTokenService.JwtToId(request); + @RequestParam(name = "page") Integer page) { + Long userId = jwtTokenService.JwtToId(request); User myPage = userService.findMyPage(userId); Level nxtLevel = userService.nextLevel(userId); Page myCommentList = commentService.getMyCommentList(userId, page); return ApiResponse.onSuccess(UserConverter.toAnswerResDTO(myPage, nxtLevel, myCommentList)); } + @PostMapping("/join")//회원가입 - @Operation(summary = "회원가입 API",description = "회원가입하는 API입니다.") + @Operation(summary = "회원가입 API", description = "회원가입하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4002",description = "NOT_ACCEPTABLE, 이미 존재하는 메일 주소입니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4002", description = "NOT_ACCEPTABLE, 이미 존재하는 메일 주소입니다."), }) - @Parameters({ }) + @Parameters({}) public ApiResponse join(@RequestBody @Valid UserRequestDTO.UserJoinRequest userJoinRequest) { - User user = userService.joinUser(userJoinRequest); - return ApiResponse.onSuccess(UserConverter.joinResultDTO(user)); + User user = userService.joinUser(userJoinRequest); + return ApiResponse.onSuccess(UserConverter.joinResultDTO(user)); } - @PostMapping ("/passwordMailSend")//비밀번호 재설정 인증 코드 전송 - @Operation(summary = "비밀번호 재설정 인증 코드 전송 API",description = "비밀번호 재설정 인증 코드 전송하는 API입니다.") + + @PostMapping("/passwordMailSend")//비밀번호 재설정 인증 코드 전송 + @Operation(summary = "비밀번호 재설정 인증 코드 전송 API", description = "비밀번호 재설정 인증 코드 전송하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), }) - @Parameters({ }) - public ApiResponse mailSend(@RequestBody @Valid UserRequestDTO.PasswordEmailSendReq emailDto){ + @Parameters({}) + public ApiResponse mailSend(@RequestBody @Valid UserRequestDTO.PasswordEmailSendReq emailDto) { System.out.println("비밀번호 재설정 인증 요청이 들어옴"); - System.out.println("비밀번호 재설정 인증 이메일 :"+emailDto.getEmail()); + System.out.println("비밀번호 재설정 인증 이메일 :" + emailDto.getEmail()); String code = mailService.passwordEmail(emailDto.getEmail()); return ApiResponse.onSuccess(UserConverter.toEmailSendRes(code)); } + @PostMapping("/passwordMailauthCheck")//이메일 코드 확인 - @Operation(summary = "비밀번호 재설정 코드 확인 API",description = "비밀번호 재설정 코드 확인하는 API입니다.") + @Operation(summary = "비밀번호 재설정 코드 확인 API", description = "비밀번호 재설정 코드 확인하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005",description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4005", description = "UNAUTHORIZED, 인증 코드가 일치하지 않습니다."), }) - @Parameters({ }) - public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.PasswordEmailSendCheckReq emailSendCheckReq){ + @Parameters({}) + public ApiResponse mailauthCheck(@RequestBody @Valid UserRequestDTO.PasswordEmailSendCheckReq emailSendCheckReq) { mailService.CheckAuthNum(emailSendCheckReq.getEmail(), emailSendCheckReq.getAuthNum()); return ApiResponse.onSuccess(null); } //로그인 @PostMapping("/login") - @Operation(summary = "로그인 API",description = "로그인하는 API입니다.") + @Operation(summary = "로그인 API", description = "로그인하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4010",description = "NOT_FOUND, 가입 가능한 이메일입니다.(이메일 정보가 존재하지 않습니다.)"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4008",description = "NOT_FOUND, 비밀번호가 틀렸습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4010", description = "NOT_FOUND, 가입 가능한 이메일입니다.(이메일 정보가 존재하지 않습니다.)"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4008", description = "NOT_FOUND, 비밀번호가 틀렸습니다."), }) - public ApiResponse> login(@RequestBody UserRequestDTO.UserLoginRequest userLoginRequest)throws GeneralException{ + public ApiResponse> login(@RequestBody UserRequestDTO.UserLoginRequest userLoginRequest) throws GeneralException { List tokenDTOList = userService.login(userLoginRequest); return ApiResponse.onSuccess(tokenDTOList); } // 토큰 재발급 @PostMapping("/reissue") - @Operation(summary = "토큰 재발급 API",description = "토큰 재발급하는 API입니다.") + @Operation(summary = "토큰 재발급 API", description = "토큰 재발급하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4007",description = "UNAUTHORIZED, 유효하지 않은 JWT입니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4100",description = "UNAUTHORIZED, RefreshToken값을 확인해주세요."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4007", description = "UNAUTHORIZED, 유효하지 않은 JWT입니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4100", description = "UNAUTHORIZED, RefreshToken값을 확인해주세요."), }) @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), @@ -192,24 +196,24 @@ public ApiResponse> reissue(@RequestHeader(name = "rtk") String r // 로그아웃 @PostMapping("/logout") - @Operation(summary = "로그아웃 API",description = "로그아웃하는 API입니다.") + @Operation(summary = "로그아웃 API", description = "로그아웃하는 API입니다.") @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001",description = "NOT_FOUND, 회원정보가 존재하지 않습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 회원정보가 존재하지 않습니다."), }) @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) - public ApiResponse logout(@RequestHeader(name = "atk") String atk, HttpServletRequest request) { + public ApiResponse logout(@RequestHeader(name = "atk") String atk, HttpServletRequest request) { return ApiResponse.onSuccess(userService.logout(request)); } @GetMapping("/point") @Operation(summary = "포인트 조회 API", description = "유저의 포인트 내역을 조회하는 API입니다") public ApiResponse myPoint(@RequestHeader("atk") String atk, - HttpServletRequest request2) { + HttpServletRequest request2) { - Long userId=jwtTokenService.JwtToId(request2); + Long userId = jwtTokenService.JwtToId(request2); Integer point = userService.pointCheck(userId); return ApiResponse.onSuccess(UserConverter.toPointViewResDTO(point)); } @@ -236,7 +240,7 @@ public ApiResponse> kakaoLogin(@RequestParam("code") String code) public ApiResponse updatePassword( @RequestHeader(name = "email") String mail, HttpServletRequest request, - @RequestBody @Valid UserRequestDTO.PasswordUpdateReq passwordUpdateReq){ + @RequestBody @Valid UserRequestDTO.PasswordUpdateReq passwordUpdateReq) { String email = userService.getEmail(request); User updPassword = userService.updatePassword(email, passwordUpdateReq); diff --git a/src/main/java/friend/spring/web/controller/VoteRestController.java b/src/main/java/friend/spring/web/controller/VoteRestController.java index 2e850c3..f4ca0b5 100644 --- a/src/main/java/friend/spring/web/controller/VoteRestController.java +++ b/src/main/java/friend/spring/web/controller/VoteRestController.java @@ -27,49 +27,50 @@ public class VoteRestController { private final JwtTokenService jwtTokenService; private final VoteService voteService; + @PostMapping("/{post-id}/generalVote") @Operation(summary = "일반 투표 API", description = "일반 투표에 참여합니다.") @Parameters({ - @Parameter(name="selectList", description=" 투표 후보 id 리스트"), + @Parameter(name = "selectList", description = " 투표 후보 id 리스트"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GeneralVoteRequestDTO request, - @PathVariable(name="post-id")Long PostId, + @PathVariable(name = "post-id") Long PostId, @RequestHeader("atk") String atk, - HttpServletRequest request2){ - Long UserId=jwtTokenService.JwtToId(request2); - General_vote generalVote= voteService.castGeneralVote(request,PostId,UserId); + HttpServletRequest request2) { + Long UserId = jwtTokenService.JwtToId(request2); + General_vote generalVote = voteService.castGeneralVote(request, PostId, UserId); return ApiResponse.onSuccess(VoteConverter.toAddGeneralVoteResultDTO(generalVote)); } @PostMapping("/{post-id}/gaugeVote") @Operation(summary = "게이지 투표 API", description = "게이지 투표에 참여합니다") @Parameters({ - @Parameter(name="gauge", description=" 게이지"), + @Parameter(name = "gauge", description = " 게이지"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.GaugeVoteRequestDTO request, - @PathVariable(name="post-id")Long PostId, + @PathVariable(name = "post-id") Long PostId, @RequestHeader("atk") String atk, HttpServletRequest request2 - ){ - Long UserId=jwtTokenService.JwtToId(request2); - Gauge_vote gaugeVote= voteService.castGaugeVote(request,PostId,UserId); + ) { + Long UserId = jwtTokenService.JwtToId(request2); + Gauge_vote gaugeVote = voteService.castGaugeVote(request, PostId, UserId); return ApiResponse.onSuccess(VoteConverter.toAddGaugelVoteResultDTO(gaugeVote)); } @PostMapping("/{post-id}/cardVote") @Operation(summary = "카드 투표 API", description = "카드 투표에 참여합니다.") @Parameters({ - @Parameter(name="selectList", description=" 투표 후보 id 리스트"), + @Parameter(name = "selectList", description = " 투표 후보 id 리스트"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken") }) public ApiResponse join(@RequestBody @Valid VoteRequestDTO.CardVoteRequestDTO request, - @PathVariable(name="post-id")Long PostId, + @PathVariable(name = "post-id") Long PostId, @RequestHeader("atk") String atk, - HttpServletRequest request2){ - Long UserId=jwtTokenService.JwtToId(request2); - Card_vote cardVote= voteService.castCardVote(request,PostId,UserId); + HttpServletRequest request2) { + Long UserId = jwtTokenService.JwtToId(request2); + Card_vote cardVote = voteService.castCardVote(request, PostId, UserId); return ApiResponse.onSuccess(VoteConverter.toAddCardVoteResultDTO(cardVote)); } } diff --git a/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java b/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java index 351e6d2..b01c071 100644 --- a/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/AlarmResponseDTO.java @@ -14,14 +14,15 @@ public class AlarmResponseDTO { @Getter @NoArgsConstructor @AllArgsConstructor - public static class AlarmListResDTO{ + public static class AlarmListResDTO { List alarmList; } + @Builder @Getter @NoArgsConstructor @AllArgsConstructor - public static class AlarmResDTO{ + public static class AlarmResDTO { Long alarmId; String userNickname; String userPhoto; @@ -38,7 +39,7 @@ public static class AlarmResDTO{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class AlarmLeftResDTO{ + public static class AlarmLeftResDTO { Boolean isAlarmLeft; } } diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index b78da1d..790d956 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -57,6 +57,7 @@ public static class commentSelectRes { Long commentChoiceId; Integer point; } + @Builder @Getter @NoArgsConstructor diff --git a/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java b/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java index f01470c..ca6e508 100644 --- a/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageRequestDTO.java @@ -15,7 +15,7 @@ public class MyPageRequestDTO { @Getter @NoArgsConstructor @AllArgsConstructor - public static class ProfileEditNameReq{ + public static class ProfileEditNameReq { @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 @NotEmpty(message = "이메일을 입력해 주세요") @@ -28,7 +28,7 @@ public static class ProfileEditNameReq{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class ProfileEditEmailReq{ + public static class ProfileEditEmailReq { @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 @NotEmpty(message = "이메일을 입력해 주세요") @@ -41,7 +41,7 @@ public static class ProfileEditEmailReq{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class ProfileEditPhoneReq{ + public static class ProfileEditPhoneReq { @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 @NotEmpty(message = "이메일을 입력해 주세요") @@ -54,7 +54,7 @@ public static class ProfileEditPhoneReq{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class ProfileEditPasswordReq{ + public static class ProfileEditPasswordReq { String curPassword; String changePassword; String checkPassword; @@ -64,7 +64,7 @@ public static class ProfileEditPasswordReq{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class ProfileEditSecurityReq{ + public static class ProfileEditSecurityReq { @Email//1)@기호를 포함해야 한다.2_@기호를 기준으로 이메일 주소를 이루는 로컬호스트와 도메인 파트가 존재해야 한다.3)도메인 파트는 최소하나의 점과 //그 뒤에 최소한 2개의 알파벳을 가진다를 검증 @NotEmpty(message = "이메일을 입력해 주세요") @@ -80,7 +80,7 @@ public static class ProfileEditSecurityReq{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class MyInquiryReq{ + public static class MyInquiryReq { InquiryCategory inquiryCategory; String content; } diff --git a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java index 32224fc..26b16b9 100644 --- a/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/MyPageResponseDTO.java @@ -18,7 +18,7 @@ public class MyPageResponseDTO { @Getter @NoArgsConstructor @AllArgsConstructor - public static class CategoryResDTO{ + public static class CategoryResDTO { Long categoryId; String category; } @@ -27,7 +27,7 @@ public static class CategoryResDTO{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class SavedCategoryResDTO{ + public static class SavedCategoryResDTO { List postCategoryList; } @@ -35,7 +35,7 @@ public static class SavedCategoryResDTO{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class SavedPostResDTO{ + public static class SavedPostResDTO { Long postId; Long ago; String title; @@ -48,7 +48,7 @@ public static class SavedPostResDTO{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class SavedAllPostResDTO{ + public static class SavedAllPostResDTO { List postList; } @@ -56,7 +56,7 @@ public static class SavedAllPostResDTO{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class MyProfileResDTO{ + public static class MyProfileResDTO { String userImage; String nickName; String email; @@ -67,7 +67,7 @@ public static class MyProfileResDTO{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class ProfileEditNameRes{ + public static class ProfileEditNameRes { String nickName; } @@ -75,7 +75,7 @@ public static class ProfileEditNameRes{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class ProfileEditEmailRes{ + public static class ProfileEditEmailRes { String changeEmail; } @@ -83,7 +83,7 @@ public static class ProfileEditEmailRes{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class ProfileEditPhoneRes{ + public static class ProfileEditPhoneRes { String phone; } @@ -91,7 +91,7 @@ public static class ProfileEditPhoneRes{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class ProfileEditPasswordRes{ + public static class ProfileEditPasswordRes { String changePassword; } @@ -99,14 +99,15 @@ public static class ProfileEditPasswordRes{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class MyInquiryRes{ + public static class MyInquiryRes { Long inquiry_id; } + @Builder @Getter @NoArgsConstructor @AllArgsConstructor - public static class SavedPostCategoryDetailRes{ + public static class SavedPostCategoryDetailRes { Long postId; Long ago; String title; @@ -114,11 +115,12 @@ public static class SavedPostCategoryDetailRes{ Integer postLike; Integer comment; } + @Builder @Getter @NoArgsConstructor @AllArgsConstructor - public static class SavedPostCategoryDetailListRes{ + public static class SavedPostCategoryDetailListRes { String name; List postList; } @@ -128,14 +130,15 @@ public static class SavedPostCategoryDetailListRes{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class NoticeListRes{ + public static class NoticeListRes { List noticeList; } + @Builder @Getter @NoArgsConstructor @AllArgsConstructor - public static class NoticeRes{ + public static class NoticeRes { String adminImage; Long ago; String title; @@ -146,7 +149,7 @@ public static class NoticeRes{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class NoticeDetailRes{ + public static class NoticeDetailRes { String adminImage; String adminName; LocalDateTime createdAt; @@ -158,7 +161,7 @@ public static class NoticeDetailRes{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class TermRes{ + public static class TermRes { String content; } @@ -166,7 +169,7 @@ public static class TermRes{ @Getter @NoArgsConstructor @AllArgsConstructor - public static class PrivacyRes{ + public static class PrivacyRes { String content; } } diff --git a/src/main/java/friend/spring/web/dto/ParentPollDTO.java b/src/main/java/friend/spring/web/dto/ParentPollDTO.java index 89f6bf4..9e85f84 100644 --- a/src/main/java/friend/spring/web/dto/ParentPollDTO.java +++ b/src/main/java/friend/spring/web/dto/ParentPollDTO.java @@ -7,7 +7,7 @@ @Data @NoArgsConstructor @AllArgsConstructor -public class ParentPollDTO{ +public class ParentPollDTO { String candidateName; String candidateImage; Long candidateId; diff --git a/src/main/java/friend/spring/web/dto/ParentPostDTO.java b/src/main/java/friend/spring/web/dto/ParentPostDTO.java index f38f28f..64b27ca 100644 --- a/src/main/java/friend/spring/web/dto/ParentPostDTO.java +++ b/src/main/java/friend/spring/web/dto/ParentPostDTO.java @@ -38,7 +38,7 @@ public static class CandidatePostDTO { @Data @NoArgsConstructor @AllArgsConstructor - public static class ParentPostGetListDTO{ + public static class ParentPostGetListDTO { List candidatePostDTOList; private Boolean isEnd; } diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index 556b3e5..6619638 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -14,7 +14,7 @@ public class PostRequestDTO { @Getter - public static class AddPostDTO{ + public static class AddPostDTO { @TitleTextLimit String title; @ContentTextLimit @@ -31,8 +31,9 @@ public static class AddPostDTO{ Integer point; List fileBase64List; } + @Getter - public static class ReviewPostGetDTO{ + public static class ReviewPostGetDTO { Integer arrange; //조회순 :0, 최신순:1 } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 8f86d86..8cf5000 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -1,4 +1,5 @@ package friend.spring.web.dto; + import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; import lombok.AllArgsConstructor; @@ -62,15 +63,16 @@ public static class PostDetailResponse { @Data @NoArgsConstructor @AllArgsConstructor - public static class PollPostGetListDTO{ + public static class PollPostGetListDTO { List pollPostList; private Boolean isEnd; } + @Builder @Data @NoArgsConstructor @AllArgsConstructor - public static class PollPostGetResponse{ + public static class PollPostGetResponse { Boolean onGoing; Boolean isVoted; Long postId; @@ -99,15 +101,16 @@ public static class PollPostGetResponse{ @Data @NoArgsConstructor @AllArgsConstructor - public static class ReviewPostGetListDTO{ + public static class ReviewPostGetListDTO { List reviewPostList; private Boolean isEnd; } + @Builder @Data @NoArgsConstructor @AllArgsConstructor - public static class ReviewPostGetResponse{ + public static class ReviewPostGetResponse { Long postId; String nickname; String userImg; diff --git a/src/main/java/friend/spring/web/dto/SseResponseDTO.java b/src/main/java/friend/spring/web/dto/SseResponseDTO.java index 4096039..86ca33d 100644 --- a/src/main/java/friend/spring/web/dto/SseResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/SseResponseDTO.java @@ -27,7 +27,7 @@ public static class CommentCreateResDTO { @Getter @NoArgsConstructor @AllArgsConstructor - public static class VoteFinishResDTO{ + public static class VoteFinishResDTO { String alarmContent; String alarmType; Long postId; diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 897dded..3f27fb4 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -122,7 +122,8 @@ public static class PasswordEmailSendCheckReq { private String name; private String authNum; } -//비밀번호 변경 + + //비밀번호 변경 @NoArgsConstructor @AllArgsConstructor @Getter diff --git a/src/main/java/friend/spring/web/dto/UserResponseDTO.java b/src/main/java/friend/spring/web/dto/UserResponseDTO.java index 021fd62..a20cfa4 100644 --- a/src/main/java/friend/spring/web/dto/UserResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/UserResponseDTO.java @@ -46,7 +46,6 @@ public static class UserInfo { } - @Builder @Getter @NoArgsConstructor @@ -97,7 +96,7 @@ public static class AnswerResDTO { Double adoptCommentPercent; List commentList; } - + @Builder @Getter @NoArgsConstructor @@ -139,7 +138,7 @@ public static class UserSummaryInfo { @Getter @NoArgsConstructor @AllArgsConstructor - public static class PasswordUpdateRes{ + public static class PasswordUpdateRes { String newPassword; } } diff --git a/src/main/java/friend/spring/web/dto/VoteRequestDTO.java b/src/main/java/friend/spring/web/dto/VoteRequestDTO.java index 63cc7a9..49c3023 100644 --- a/src/main/java/friend/spring/web/dto/VoteRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/VoteRequestDTO.java @@ -8,17 +8,17 @@ public class VoteRequestDTO { @Getter - public static class GeneralVoteRequestDTO{ + public static class GeneralVoteRequestDTO { List selectList; } @Getter - public static class GaugeVoteRequestDTO{ + public static class GaugeVoteRequestDTO { Integer value; } @Getter - public static class CardVoteRequestDTO{ + public static class CardVoteRequestDTO { List selectList; } } From 49fad7029335ffb11b1775ed0b1d60c38db0dd65 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Wed, 28 Feb 2024 21:31:38 +0900 Subject: [PATCH 231/255] =?UTF-8?q?=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EC=9E=AC=EC=84=A4=EC=A0=95=20=EB=A6=AC=ED=84=B4=EA=B0=92=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/service/UserServiceImpl.java | 6 +----- .../friend/spring/web/controller/UserRestController.java | 5 ++--- src/main/resources/application.yml | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 6b0ada1..fa5e8a6 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -210,9 +210,5 @@ public String getEmail(HttpServletRequest request) { return request.getHeader("email"); } } -// -// // Request 의 Header 에서 access token 값 추출 "atk" : "token--" -// public String resolveAccessToken(HttpServletRequest request) { -// return request.getHeader("atk"); -// } + diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index df72b7a..766d9b6 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -2,7 +2,6 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.apiPayload.GeneralException; -import friend.spring.converter.MyPageConverter; import friend.spring.converter.UserConverter; import friend.spring.domain.Comment; import friend.spring.domain.Level; @@ -228,7 +227,7 @@ public ApiResponse> kakaoLogin(@RequestParam("code") String code) return ApiResponse.onSuccess(authService.kakaoLogin(code)); } - + //비밀번호 재설정 @PatchMapping(value = "/updatePassword") @Operation(summary = "비밀번호 재설정 API", description = "(비밀번호 재설정 이메일 인증후) 비밀번호를 변경하는 API") @ApiResponses({ @@ -244,7 +243,7 @@ public ApiResponse updatePassword( String email = userService.getEmail(request); User updPassword = userService.updatePassword(email, passwordUpdateReq); - return ApiResponse.onSuccess(UserConverter.toUpdatePassword(updPassword)); + return ApiResponse.onSuccess(null); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index b25bdb6..4f9a80a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -65,6 +65,6 @@ mail: kakao: auth: client: ${KAKAO_AUTH_CLIENT} - redirect-uri: ${KAKAO_AUTH_REDIRECT_URI} + redirect_uri: ${KAKAO_AUTH_REDIRECT_URI} secret_key: ${KAKAO_AUTH_SECRET_KEY} From 2d6f49e40a82d15fc0b8f79304df4e5bad16c741 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Wed, 28 Feb 2024 22:27:03 +0900 Subject: [PATCH 232/255] =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=ED=83=88=ED=87=B4?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/service/UserService.java | 2 ++ .../spring/service/UserServiceImpl.java | 26 +++++++++++++++++++ .../web/controller/UserRestController.java | 13 ++++++++++ .../friend/spring/web/dto/UserRequestDTO.java | 8 ++++++ 4 files changed, 49 insertions(+) diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index 29f4b6c..f40394c 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -31,4 +31,6 @@ public interface UserService { User updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwordUpdateReq); String getEmail(HttpServletRequest request); + + String deactivateUser(HttpServletRequest request); } diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index fa5e8a6..63ad46f 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -209,6 +209,32 @@ public User updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwo public String getEmail(HttpServletRequest request) { return request.getHeader("email"); } + + // 회원 탈퇴 - userIdx + @Transactional + public String deactivateUser(HttpServletRequest request) throws GeneralException { + Long userIdx = jwtTokenProvider.getCurrentUser(request); + + System.out.println("getCurrentUser()로 가져온 userIdx : "+userIdx); + User user = userRepository.findById(userIdx) + .orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); + + // Redis에 로그인되어있는 토큰 삭제 + // Redis 에서 해당 User email 로 저장된 Refresh Token 이 있는지 여부를 확인 후 있을 경우 삭제 + if (redisTemplate.opsForValue().get("RT:" + user.getEmail()) != null) { + // Refresh Token 삭제 + redisTemplate.delete("RT:" + user.getEmail()); + } + String accessToken = jwtTokenProvider.resolveAccessToken(request); + // 탈퇴한 토큰을 차단 (deactivateUser 토큰 블랙리스트) + Long expiration = jwtTokenProvider.getExpireTime(accessToken).getTime(); + // Redis 에 --accesstoken--(key) : logout(value) 로 저장, token 만료시간 지나면 자동 삭제 + redisTemplate.opsForValue().set(accessToken, "logout", expiration, TimeUnit.MILLISECONDS); + + userRepository.deleteById(user.getId()); + + return "회원 탈퇴 성공"; + } } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 766d9b6..62822c4 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -247,4 +247,17 @@ public ApiResponse updatePassword( } + // 회원 탈퇴 + @DeleteMapping("/delete") + @Operation(summary = "회원 탈퇴 API", description = "회원을 탈퇴시키는 API") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 회원정보가 존재하지 않습니다."), + }) + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 회원 탈퇴할 회원의 accessToken"), + }) + public ApiResponse deactivateUser(@RequestHeader(name = "atk") String atk, HttpServletRequest request) throws GeneralException { + return ApiResponse.onSuccess(userService.deactivateUser(request)); + } } diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 3f27fb4..7bc997e 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -134,4 +134,12 @@ public static class PasswordUpdateReq { private String newPassword; private String newPasswordCheck; } + //회원 탈퇴 + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Setter + public static class Delete { + private String email; + } } \ No newline at end of file From 897354268769619973a0b3c20111a4375d192d15 Mon Sep 17 00:00:00 2001 From: park sang woo Date: Wed, 28 Feb 2024 23:24:46 +0900 Subject: [PATCH 233/255] =?UTF-8?q?=EC=BD=94=EB=A9=98=ED=8A=B8=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/friend/spring/converter/UserConverter.java | 5 ----- src/main/java/friend/spring/domain/User.java | 6 +++++- src/main/java/friend/spring/service/UserService.java | 3 +-- .../java/friend/spring/service/UserServiceImpl.java | 10 +++++----- .../spring/web/controller/UserRestController.java | 5 ++--- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/main/java/friend/spring/converter/UserConverter.java b/src/main/java/friend/spring/converter/UserConverter.java index 0783a05..301404a 100644 --- a/src/main/java/friend/spring/converter/UserConverter.java +++ b/src/main/java/friend/spring/converter/UserConverter.java @@ -205,9 +205,4 @@ public static User KakaoUser( } - public static UserResponseDTO.PasswordUpdateRes toUpdatePassword(User user) { - return UserResponseDTO.PasswordUpdateRes.builder() - .newPassword(user.getPassword()) - .build(); - } } diff --git a/src/main/java/friend/spring/domain/User.java b/src/main/java/friend/spring/domain/User.java index 227eb8f..9a98def 100644 --- a/src/main/java/friend/spring/domain/User.java +++ b/src/main/java/friend/spring/domain/User.java @@ -58,7 +58,7 @@ public class User extends BaseEntity implements UserDetails { @Column(nullable = true) private Boolean agree_info; - @Column(nullable = true)//잠시 true로 수정 + @Column(nullable = true) private Boolean is_deleted; @Column(nullable = true) @@ -193,5 +193,9 @@ public void setPhone(String phone) { public void setPassword(String password) { this.password = password; } + + public void setIsDeleted(boolean deleted) { + this.is_deleted = deleted; + } } diff --git a/src/main/java/friend/spring/service/UserService.java b/src/main/java/friend/spring/service/UserService.java index f40394c..cdca44f 100644 --- a/src/main/java/friend/spring/service/UserService.java +++ b/src/main/java/friend/spring/service/UserService.java @@ -2,7 +2,6 @@ import friend.spring.domain.Level; import friend.spring.domain.User; -import friend.spring.web.dto.MyPageRequestDTO; import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; @@ -28,7 +27,7 @@ public interface UserService { List reissue(HttpServletRequest request); - User updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwordUpdateReq); + void updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwordUpdateReq); String getEmail(HttpServletRequest request); diff --git a/src/main/java/friend/spring/service/UserServiceImpl.java b/src/main/java/friend/spring/service/UserServiceImpl.java index 63ad46f..b81f7d7 100644 --- a/src/main/java/friend/spring/service/UserServiceImpl.java +++ b/src/main/java/friend/spring/service/UserServiceImpl.java @@ -11,7 +11,6 @@ import friend.spring.security.JwtTokenProvider; import friend.spring.web.dto.TokenDTO; import friend.spring.web.dto.UserRequestDTO; -import io.jsonwebtoken.io.IOException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; @@ -26,7 +25,6 @@ import java.util.concurrent.TimeUnit; import static friend.spring.apiPayload.code.status.ErrorStatus.*; -import static java.util.regex.Pattern.matches; @Slf4j @Service @@ -185,7 +183,7 @@ private boolean isValidPassword(String password) { } //비밀번호 변경 - public User updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwordUpdateReq) throws GeneralException { + public void updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwordUpdateReq) throws GeneralException { User user = userRepository.findByEmail(email).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); String newPassword = passwordUpdateReq.getNewPassword(); @@ -202,7 +200,7 @@ public User updatePassword(String email, UserRequestDTO.PasswordUpdateReq passwo user.setPassword(encoder.encode(newPassword)); } userRepository.save(user); - return user; + } // Request 의 Header 에서 email 값 추출 "email" : "gominchingu@gmail.com" @@ -231,7 +229,9 @@ public String deactivateUser(HttpServletRequest request) throws GeneralException // Redis 에 --accesstoken--(key) : logout(value) 로 저장, token 만료시간 지나면 자동 삭제 redisTemplate.opsForValue().set(accessToken, "logout", expiration, TimeUnit.MILLISECONDS); - userRepository.deleteById(user.getId()); +// userRepository.deleteById(user.getId()); + user.setIsDeleted(true); + userRepository.save(user); return "회원 탈퇴 성공"; } diff --git a/src/main/java/friend/spring/web/controller/UserRestController.java b/src/main/java/friend/spring/web/controller/UserRestController.java index 62822c4..b762ec4 100644 --- a/src/main/java/friend/spring/web/controller/UserRestController.java +++ b/src/main/java/friend/spring/web/controller/UserRestController.java @@ -236,12 +236,11 @@ public ApiResponse> kakaoLogin(@RequestParam("code") String code) @Parameters({ @Parameter(name = "email", description = "RequestHeader - 비밀번호를 바꾸고자 하는 사용자의 email") }) - public ApiResponse updatePassword( + public ApiResponse updatePassword( @RequestHeader(name = "email") String mail, HttpServletRequest request, @RequestBody @Valid UserRequestDTO.PasswordUpdateReq passwordUpdateReq) { - String email = userService.getEmail(request); - User updPassword = userService.updatePassword(email, passwordUpdateReq); + userService.updatePassword(userService.getEmail(request),passwordUpdateReq ); return ApiResponse.onSuccess(null); From 8add49282971b42205a9ab8bb8fa138d37f6d52d Mon Sep 17 00:00:00 2001 From: hjh Date: Thu, 29 Feb 2024 12:06:59 +0900 Subject: [PATCH 234/255] =?UTF-8?q?#178=20createdAt=20null=EB=A1=9C=20?= =?UTF-8?q?=EB=82=98=EC=98=A4=EB=8A=94=20=ED=98=84=EC=83=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/converter/PostConverter.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 3a2f7a9..76da35f 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -263,7 +263,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B userFile = userFileOptional.get(); userImg = userFile.getUrl(); } - +//리뷰글 if (post.getPostType() == REVIEW) { return PostResponseDTO.PostDetailResponse.builder() .postType(REVIEW) @@ -283,6 +283,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .myPost(myPost) .build(); } +//게이지 투표 if (post.getVoteType() == PostVoteType.GAUGE) { //나노초 단위로 마감 여부 확인 @@ -327,6 +328,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .myPost(myPost) .build(); } +//일반 투표 if (post.getVoteType() == PostVoteType.GENERAL) { //나노초 단위로 마감 여부 확인 LocalDateTime now = LocalDateTime.now(); @@ -336,6 +338,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B //투표 후보 리스트 List pollOptionDTOList = post.getGeneralPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); + //투표 마감시 if (post.getGeneralPoll().getDeadline().isAfter(LocalDateTime.now())) { if (engage) { //투표한 후보에 대한 정보 @@ -556,6 +559,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) .userImg(userImg) + .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) .file(FileConverter.toFileDTO(post.getFileList())) @@ -692,7 +696,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .myPost(myPost) .build(); } -//일반 투표 마감 후 +//카드 투표 마감 후 //투표한 후보에 대한 정보 Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() .filter(cardVote -> cardVote.getUser().getId().equals(userId)) @@ -807,6 +811,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) .userImg(userImg) + .createdAt(post.getCreatedAt()) .title(post.getTitle()) .content(post.getContent()) .file(FileConverter.toFileDTO(post.getFileList())) From 4d7871fcb6df8c30bb5a01492b40d346bb6725a1 Mon Sep 17 00:00:00 2001 From: hjh Date: Thu, 29 Feb 2024 18:20:25 +0900 Subject: [PATCH 235/255] =?UTF-8?q?#178=20=EC=83=81=EC=84=B8=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=EC=8B=9C=20=EB=A7=88=EA=B0=90=20=EC=95=88=EB=90=90?= =?UTF-8?q?=EC=9D=84=EB=95=8C=EB=8F=84=20allCandidate=20=EB=82=98=EC=98=A4?= =?UTF-8?q?=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 147 ++++++++++++------ 1 file changed, 96 insertions(+), 51 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 76da35f..2ae4dfa 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -338,8 +338,25 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B //투표 후보 리스트 List pollOptionDTOList = post.getGeneralPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - //투표 마감시 + + ////////////////////////////////////////////////////////////////////////////////////////////// + long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + allCandidatePercent = post.getGeneralPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId = candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + ////////////////////////////////////////////////////// + //투표 마감x if (post.getGeneralPoll().getDeadline().isAfter(LocalDateTime.now())) { + if (engage) { //투표한 후보에 대한 정보 Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() @@ -359,14 +376,14 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .collect(Collectors.toList()); // 총 투표수 계산 - long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); +// long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() +// .flatMap(vote -> vote.getSelect_list().stream()) +// .count(); - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); +// // 각 후보별 선택된 횟수 계산 +// Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() +// .flatMap(vote -> vote.getSelect_list().stream()) +// .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); // 사용자가 선택한 후보의 선택률 계산 userVotePercent = userSelectedCandidateIds.stream() @@ -459,14 +476,15 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .filter(vote -> vote.getUser().getId().equals(userId)) .flatMap(vote -> vote.getSelect_list().stream()) .collect(Collectors.toList()); - // 총 투표수 계산 - long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); +// // 총 투표수 계산 +// long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() +// .flatMap(vote -> vote.getSelect_list().stream()) +// .count(); +// // 각 후보별 선택된 횟수 계산 +// Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() +// .flatMap(vote -> vote.getSelect_list().stream()) +// .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + // 사용자가 선택한 후보의 선택률 계산 userVotePercent = userSelectedCandidateIds.stream() .map(candidateId -> { @@ -591,6 +609,32 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B //투표 후보 리스트 List pollOptionDTOList = post.getCardPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); + + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); + + // 총 투표수 계산 + long totalVotes = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .count(); + + + // 각 후보별 선택된 횟수 계산 + Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + allCandidatePercent = post.getCardPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId = candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + if (post.getCardPoll().getDeadline().isAfter(LocalDateTime.now())) { if (engage) { //투표한 후보에 대한 정보 @@ -604,21 +648,21 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .collect(Collectors.toList()); // 총 투표수 계산 - // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() - .filter(vote -> vote.getUser().getId().equals(userId)) - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.toList()); - - // 총 투표수 계산 - long totalVotes = post.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); - - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); +// // 사용자가 투표한 후보의 ID +// List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() +// .filter(vote -> vote.getUser().getId().equals(userId)) +// .flatMap(vote -> vote.getSelect_list().stream()) +// .collect(Collectors.toList()); +// +// // 총 투표수 계산 +// long totalVotes = post.getCardPoll().getCardVoteList().stream() +// .flatMap(vote -> vote.getSelect_list().stream()) +// .count(); +// +// // 각 후보별 선택된 횟수 계산 +// Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() +// .flatMap(vote -> vote.getSelect_list().stream()) +// .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); // 사용자가 선택한 후보의 선택률 계산 userVotePercent = userSelectedCandidateIds.stream() @@ -706,19 +750,19 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .filter(candidate -> selectedOptionIds.contains(candidate.getId())) .map(PostConverter::toPollOptionResDTO) .collect(Collectors.toList()); - // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() - .filter(vote -> vote.getUser().getId().equals(userId)) - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.toList()); - // 총 투표수 계산 - long totalVotes = post.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); +// // 사용자가 투표한 후보의 ID +// List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() +// .filter(vote -> vote.getUser().getId().equals(userId)) +// .flatMap(vote -> vote.getSelect_list().stream()) +// .collect(Collectors.toList()); +// // 총 투표수 계산 +// long totalVotes = post.getCardPoll().getCardVoteList().stream() +// .flatMap(vote -> vote.getSelect_list().stream()) +// .count(); +// // 각 후보별 선택된 횟수 계산 +// Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() +// .flatMap(vote -> vote.getSelect_list().stream()) +// .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); // 사용자가 선택한 후보의 선택률 계산 userVotePercent = userSelectedCandidateIds.stream() .map(candidateId -> { @@ -752,13 +796,13 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B }) .collect(Collectors.toList()); - allCandidatePercent = post.getCardPoll().getCandidateList().stream() - .map(candidate -> { - Long candidateId = candidate.getId(); - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); +// allCandidatePercent = post.getCardPoll().getCandidateList().stream() +// .map(candidate -> { +// Long candidateId = candidate.getId(); +// long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); +// return (int) ((double) selectionCount / totalVotes * 100); +// }) +// .collect(Collectors.toList()); userVoteResult = userSelectedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); @@ -936,6 +980,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, }) .collect(Collectors.toList()); + return PostResponseDTO.PollPostGetResponse.builder() .onGoing(true) .isVoted(true) From bd689babc0fb4f6f25f5026b4852543b0438b0aa Mon Sep 17 00:00:00 2001 From: hjh Date: Thu, 29 Feb 2024 19:03:43 +0900 Subject: [PATCH 236/255] =?UTF-8?q?#178=20=ED=9B=84=EA=B8=B0=EA=B8=80=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=EB=B3=B4=EA=B8=B0=EC=8B=9C=20=EC=9B=90?= =?UTF-8?q?=EA=B8=80=20=EC=A0=95=EB=B3=B4&ID,=20=EA=B8=80=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=EB=B3=B4=EA=B8=B0=EC=8B=9C=20=ED=9B=84=EA=B8=B0?= =?UTF-8?q?=EA=B8=80=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20id,=20voteType=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 51 +++++++++++-------- .../friend/spring/web/dto/ParentPostDTO.java | 4 ++ .../spring/web/dto/PostResponseDTO.java | 1 + 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 2ae4dfa..058648b 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -64,6 +64,8 @@ public static ParentPostDTO toParentPostDTO(Post parentPost) { if (parentPost.getVoteType() == PostVoteType.GAUGE) { return ParentPostDTO.builder() + .postId(parentPost.getId()) + .postVoteType(parentPost.getVoteType()) .nickname(parentPost.getUser().getNickname()) .userImg(userImg) .title(parentPost.getTitle()) @@ -123,6 +125,8 @@ public static ParentPostDTO toParentPostDTO(Post parentPost) { return ParentPostDTO.builder() + .postId(parentPost.getId()) + .postVoteType(parentPost.getVoteType()) .nickname(parentPost.getUser().getNickname()) .userImg(userImg) .title(parentPost.getTitle()) @@ -179,6 +183,8 @@ public static ParentPostDTO toParentPostDTO(Post parentPost) { return ParentPostDTO.builder() + .postId(parentPost.getId()) + .postVoteType(parentPost.getVoteType()) .nickname(parentPost.getUser().getNickname()) .userImg(userImg) .title(parentPost.getTitle()) @@ -1535,6 +1541,27 @@ public static PostResponseDTO.PollPostGetListDTO pollPostGetListDTO(Page p .build(); } + public static ParentPostDTO.CandidatePostDTO candidatePostDTO(Post post) { + Integer likeCount = post.getPostLikeList().size(); + Integer commentCount = post.getCommentList().size(); + return ParentPostDTO.CandidatePostDTO.builder() + .postId(post.getId()) + .title(post.getTitle()) + .content(post.getContent()) + .like(likeCount) + .comment(commentCount) + .createdAt(post.getCreatedAt()) + .build(); + } + + public static ParentPostDTO.ParentPostGetListDTO parentPostGetListDTO(Page postList, Long userId) { + List parentPostGetListDTO = postList.stream() + .map(post -> candidatePostDTO(post)).collect(Collectors.toList()); + return ParentPostDTO.ParentPostGetListDTO.builder() + .candidatePostDTOList(parentPostGetListDTO) + .isEnd(postList.isLast()) + .build(); + } public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post post, Long userId) { Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); @@ -1543,6 +1570,7 @@ public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post p File userFile = null; String userImg = null; Optional userFileOptional = Optional.ofNullable(post.getUser().getFile()); + Post parentPost= post.getParentPost(); if (userFileOptional.isPresent()) { userFile = userFileOptional.get(); @@ -1560,6 +1588,7 @@ public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post p .comment(commentCount) .isLike(isLike) .isComment(isComment) + .parentPostDTO(candidatePostDTO(parentPost)) .build(); } @@ -1572,28 +1601,6 @@ public static PostResponseDTO.ReviewPostGetListDTO reviewPostGetListDTO(Page postList, Long userId) { - List parentPostGetListDTO = postList.stream() - .map(post -> candidatePostDTO(post)).collect(Collectors.toList()); - return ParentPostDTO.ParentPostGetListDTO.builder() - .candidatePostDTOList(parentPostGetListDTO) - .isEnd(postList.isLast()) - .build(); - } - public static PostResponseDTO.MyPostDTO toMyPostResDTO(Post post) { return PostResponseDTO.MyPostDTO.builder() .postId(post.getId()) diff --git a/src/main/java/friend/spring/web/dto/ParentPostDTO.java b/src/main/java/friend/spring/web/dto/ParentPostDTO.java index 64b27ca..24c9388 100644 --- a/src/main/java/friend/spring/web/dto/ParentPostDTO.java +++ b/src/main/java/friend/spring/web/dto/ParentPostDTO.java @@ -1,5 +1,7 @@ package friend.spring.web.dto; +import friend.spring.domain.enums.PostType; +import friend.spring.domain.enums.PostVoteType; import lombok.*; import java.time.LocalDateTime; @@ -11,6 +13,8 @@ @NoArgsConstructor @AllArgsConstructor public class ParentPostDTO { + Long postId; + PostVoteType postVoteType; String nickname; String userImg; String title; diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 8cf5000..597b4e8 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -122,6 +122,7 @@ public static class ReviewPostGetResponse { Integer comment; Boolean isLike; Boolean isComment; + ParentPostDTO.CandidatePostDTO parentPostDTO; } @Builder From 6aece5b09e2f9a28b65528b831179d05369d8435 Mon Sep 17 00:00:00 2001 From: hjh Date: Fri, 1 Mar 2024 03:18:51 +0900 Subject: [PATCH 237/255] =?UTF-8?q?#186=20=EC=BD=94=EB=93=9C=20=EA=B0=84?= =?UTF-8?q?=EA=B2=A8=EB=A1=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 1021 +++-------------- 1 file changed, 160 insertions(+), 861 deletions(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 058648b..45d6ed2 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -22,6 +22,7 @@ import friend.spring.web.dto.CandidateResponseDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; +import software.amazon.awssdk.services.s3.endpoints.internal.Value; import java.util.List; @@ -345,10 +346,12 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B List pollOptionDTOList = post.getGeneralPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - ////////////////////////////////////////////////////////////////////////////////////////////// + // 총 투표수 계산 long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() .flatMap(vote -> vote.getSelect_list().stream()) .count(); + + // 각 후보별 선택된 횟수 계산 Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() .flatMap(vote -> vote.getSelect_list().stream()) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); @@ -359,159 +362,51 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); - ////////////////////////////////////////////////////// - //투표 마감x - if (post.getGeneralPoll().getDeadline().isAfter(LocalDateTime.now())) { - - if (engage) { - //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(generalVote -> generalVote.getUser().getId().equals(userId)) - .flatMap(generalVote -> generalVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - - // 총 투표수 계산 - // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(vote -> vote.getUser().getId().equals(userId)) - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.toList()); - - // 총 투표수 계산 -// long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() -// .flatMap(vote -> vote.getSelect_list().stream()) -// .count(); - -// // 각 후보별 선택된 횟수 계산 -// Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() -// .flatMap(vote -> vote.getSelect_list().stream()) -// .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - - // 사용자가 선택한 후보의 선택률 계산 - userVotePercent = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - - // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) - userVoteResult = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return String.format("%d/%d", selectionCount, totalVotes); - }) - .collect(Collectors.toList()); - isVote = true; - // 투표수가 가장 많은 후보의 선택률 계산 - OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() - .mapToDouble(aLong -> (double) aLong.getValue() / totalVotes) - .max(); - - // 선택률이 가장 높은 후보의 ID들 찾기 - List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 - topCandidateList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - - topCandidatePercent = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - - topVoteResult = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return String.format("%d/%d", selectionCount, totalVotes); - }) - .collect(Collectors.toList()); - } - return PostResponseDTO.PostDetailResponse.builder() - .OnGoing(voteOnGoing) - .isVoted(isVote) - .postType(VOTE) - .postVoteType(PostVoteType.GENERAL) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .createdAt(post.getCreatedAt()) - .title(post.getTitle()) - .content(post.getContent()) - .file(FileConverter.toFileDTO(post.getFileList())) - .pollTitle(post.getGeneralPoll().getPollTitle()) - .pollOption(pollOptionDTOList) - .topCandidate(topCandidateList) - .userVote(userChoiceList) - .userVotePercent(userVotePercent) - .userVoteResult(userVoteResult) - .topVoteResult(topVoteResult) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .point(post.getPoint()) - .deadline(post.getGeneralPoll().getDeadline()) - .view(post.getView()) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .myPost(myPost) - .build(); - } -//일반 투표 마감 후 - //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(cardVote -> cardVote.getUser().getId().equals(userId)) - .flatMap(cardVote -> cardVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(vote -> vote.getUser().getId().equals(userId)) - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.toList()); -// // 총 투표수 계산 -// long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() -// .flatMap(vote -> vote.getSelect_list().stream()) -// .count(); -// // 각 후보별 선택된 횟수 계산 -// Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() -// .flatMap(vote -> vote.getSelect_list().stream()) -// .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + if (engage) { + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); - // 사용자가 선택한 후보의 선택률 계산 - userVotePercent = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); + Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(generalVote -> generalVote.getUser().getId().equals(userId)) + .flatMap(generalVote -> generalVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + + userChoiceList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + + // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) + userVoteResult = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + isVote = true; + } - //1등 투표 계산 // 투표수가 가장 많은 후보의 선택률 계산 OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() - .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .mapToDouble(aLong -> (double) aLong.getValue() / totalVotes) .max(); // 선택률이 가장 높은 후보의 ID들 찾기 List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) .map(Map.Entry::getKey) .collect(Collectors.toList()); - - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + // 가장 높은 투표를 받은 후보들을 mostVotedCandidateIds에 담기 topCandidateList = post.getGeneralPoll().getCandidateList().stream() .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) .map(PostConverter::toPollOptionResDTO) @@ -524,61 +419,16 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B }) .collect(Collectors.toList()); - allCandidatePercent = post.getGeneralPoll().getCandidateList().stream() - .map(candidate -> { - Long candidateId = candidate.getId(); - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - userVoteResult = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return String.format("%d/%d", selectionCount, totalVotes); - }) - .collect(Collectors.toList()); topVoteResult = mostVotedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return String.format("%d/%d", selectionCount, totalVotes); }) .collect(Collectors.toList()); - if (engage) { - return PostResponseDTO.PostDetailResponse.builder() - .OnGoing(false) - .isVoted(true) - .postType(VOTE) - .postVoteType(PostVoteType.GENERAL) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .createdAt(post.getCreatedAt()) - .title(post.getTitle()) - .content(post.getContent()) - .file(FileConverter.toFileDTO(post.getFileList())) - .pollTitle(post.getGeneralPoll().getPollTitle()) - .pollOption(pollOptionDTOList) - .userVoteResult(userVoteResult) - .topVoteResult(topVoteResult) - .topCandidate(topCandidateList) - .userVote(userChoiceList) - .userVotePercent(userVotePercent) - .userVoteResult(userVoteResult) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .point(post.getPoint()) - .deadline(post.getGeneralPoll().getDeadline()) - .view(post.getView()) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .myPost(myPost) - .build(); - } return PostResponseDTO.PostDetailResponse.builder() - .OnGoing(false) - .isVoted(false) + .OnGoing(voteOnGoing) + .isVoted(isVote) .postType(VOTE) .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) @@ -589,9 +439,11 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getGeneralPoll().getPollTitle()) .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) .userVoteResult(userVoteResult) .topVoteResult(topVoteResult) - .topCandidate(topCandidateList) .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) .point(post.getPoint()) @@ -603,8 +455,6 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .isComment(isComment) .myPost(myPost) .build(); - - } //카드 투표 상세 보기 //나노초 단위로 마감 여부 확인 @@ -616,23 +466,15 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B List pollOptionDTOList = post.getCardPoll().getCandidateList().stream() .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); - // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() - .filter(vote -> vote.getUser().getId().equals(userId)) - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.toList()); - // 총 투표수 계산 long totalVotes = post.getCardPoll().getCardVoteList().stream() .flatMap(vote -> vote.getSelect_list().stream()) .count(); - // 각 후보별 선택된 횟수 계산 Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() .flatMap(vote -> vote.getSelect_list().stream()) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - allCandidatePercent = post.getCardPoll().getCandidateList().stream() .map(candidate -> { Long candidateId = candidate.getId(); @@ -640,156 +482,51 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); + if (engage) { + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); - if (post.getCardPoll().getDeadline().isAfter(LocalDateTime.now())) { - if (engage) { - //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() - .filter(CardVote -> CardVote.getUser().getId().equals(userId)) - .flatMap(CardVote -> CardVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getCardPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - - // 총 투표수 계산 -// // 사용자가 투표한 후보의 ID -// List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() -// .filter(vote -> vote.getUser().getId().equals(userId)) -// .flatMap(vote -> vote.getSelect_list().stream()) -// .collect(Collectors.toList()); -// -// // 총 투표수 계산 -// long totalVotes = post.getCardPoll().getCardVoteList().stream() -// .flatMap(vote -> vote.getSelect_list().stream()) -// .count(); -// -// // 각 후보별 선택된 횟수 계산 -// Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() -// .flatMap(vote -> vote.getSelect_list().stream()) -// .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - - // 사용자가 선택한 후보의 선택률 계산 - userVotePercent = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - - // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) - userVoteResult = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return String.format("%d/%d", selectionCount, totalVotes); - }) - .collect(Collectors.toList()); - isVote = true; - // 투표수가 가장 많은 후보의 선택률 계산 - OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() - .mapToDouble(aLong -> (double) aLong.getValue() / totalVotes) - .max(); - - // 선택률이 가장 높은 후보의 ID들 찾기 - List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 - topCandidateList = post.getCardPoll().getCandidateList().stream() - .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); + Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); - topCandidatePercent = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); + userChoiceList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); - topVoteResult = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return String.format("%d/%d", selectionCount, totalVotes); - }) - .collect(Collectors.toList()); - } - return PostResponseDTO.PostDetailResponse.builder() - .OnGoing(voteOnGoing) - .isVoted(isVote) - .postType(VOTE) - .postVoteType(PostVoteType.CARD) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .createdAt(post.getCreatedAt()) - .title(post.getTitle()) - .content(post.getContent()) - .file(FileConverter.toFileDTO(post.getFileList())) - .pollTitle(post.getCardPoll().getPollTitle()) - .pollOption(pollOptionDTOList) - .topCandidate(topCandidateList) - .userVote(userChoiceList) - .userVotePercent(userVotePercent) - .userVoteResult(userVoteResult) - .topVoteResult(topVoteResult) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .point(post.getPoint()) - .deadline(post.getCardPoll().getDeadline()) - .view(post.getView()) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .myPost(myPost) - .build(); + // 사용자가 선택한 후보의 투표 결과 정보 계산 (선택 인원/총 인원) + userVoteResult = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + isVote = true; } -//카드 투표 마감 후 - //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() - .filter(cardVote -> cardVote.getUser().getId().equals(userId)) - .flatMap(cardVote -> cardVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getCardPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); -// // 사용자가 투표한 후보의 ID -// List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() -// .filter(vote -> vote.getUser().getId().equals(userId)) -// .flatMap(vote -> vote.getSelect_list().stream()) -// .collect(Collectors.toList()); -// // 총 투표수 계산 -// long totalVotes = post.getCardPoll().getCardVoteList().stream() -// .flatMap(vote -> vote.getSelect_list().stream()) -// .count(); -// // 각 후보별 선택된 횟수 계산 -// Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() -// .flatMap(vote -> vote.getSelect_list().stream()) -// .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - // 사용자가 선택한 후보의 선택률 계산 - userVotePercent = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - //1등 투표 계산 // 투표수가 가장 많은 후보의 선택률 계산 OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() - .mapToDouble(entry -> (double) entry.getValue() / totalVotes) + .mapToDouble(aLong -> (double) aLong.getValue() / totalVotes) .max(); // 선택률이 가장 높은 후보의 ID들 찾기 List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) + .filter(entry -> Double.compare(entry.getValue(), hightestCandidate.getAsDouble() * totalVotes) == 0) .map(Map.Entry::getKey) .collect(Collectors.toList()); - - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + // 가장 높은 투표를 받은 후보들을 mostVotedCandidateIds에 담기 topCandidateList = post.getCardPoll().getCandidateList().stream() .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) .map(PostConverter::toPollOptionResDTO) @@ -802,61 +539,16 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B }) .collect(Collectors.toList()); -// allCandidatePercent = post.getCardPoll().getCandidateList().stream() -// .map(candidate -> { -// Long candidateId = candidate.getId(); -// long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); -// return (int) ((double) selectionCount / totalVotes * 100); -// }) -// .collect(Collectors.toList()); - userVoteResult = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return String.format("%d/%d", selectionCount, totalVotes); - }) - .collect(Collectors.toList()); topVoteResult = mostVotedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); return String.format("%d/%d", selectionCount, totalVotes); }) .collect(Collectors.toList()); - if (engage) { - return PostResponseDTO.PostDetailResponse.builder() - .OnGoing(false) - .isVoted(true) - .postType(VOTE) - .postVoteType(PostVoteType.CARD) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .createdAt(post.getCreatedAt()) - .title(post.getTitle()) - .content(post.getContent()) - .file(FileConverter.toFileDTO(post.getFileList())) - .pollTitle(post.getCardPoll().getPollTitle()) - .pollOption(pollOptionDTOList) - .userVoteResult(userVoteResult) - .topVoteResult(topVoteResult) - .topCandidate(topCandidateList) - .userVote(userChoiceList) - .userVotePercent(userVotePercent) - .userVoteResult(userVoteResult) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .point(post.getPoint()) - .deadline(post.getCardPoll().getDeadline()) - .view(post.getView()) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .myPost(myPost) - .build(); - } return PostResponseDTO.PostDetailResponse.builder() - .OnGoing(false) - .isVoted(false) + .OnGoing(voteOnGoing) + .isVoted(isVote) .postType(VOTE) .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) @@ -867,9 +559,11 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .file(FileConverter.toFileDTO(post.getFileList())) .pollTitle(post.getCardPoll().getPollTitle()) .pollOption(pollOptionDTOList) + .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) .userVoteResult(userVoteResult) .topVoteResult(topVoteResult) - .topCandidate(topCandidateList) .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) .point(post.getPoint()) @@ -897,17 +591,6 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, userImg = userFile.getUrl(); } - //로컬 db test - if (post.getPostType() == VOTE && post.getVoteType() == null) { - return PostResponseDTO.PollPostGetResponse.builder() - .postId(post.getId()) - .postVoteType(null) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .content(Long.toString(post.getId())) - .build(); - } - Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); List userChoiceList = null; @@ -915,178 +598,19 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Boolean isLike = !post.getPostLikeList().stream().filter(like -> like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); Boolean isComment = !post.getCommentList().stream().filter(like -> like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); Boolean engage = false; - + Boolean isVoted = false; + LocalDateTime now = LocalDateTime.now(); + //일반 투표 if (post.getVoteType() == PostVoteType.GENERAL) { - List pollOptionDTOList = post.getGeneralPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); if (!post.getGeneralPoll().getGeneralVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { engage = true; } -//일반 투표 마감 전 - if (post.getGeneralPoll().getDeadline().isAfter(LocalDateTime.now())) { - if (engage) { - //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(cardVote -> cardVote.getUser().getId().equals(userId)) - .flatMap(cardVote -> cardVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(vote -> vote.getUser().getId().equals(userId)) - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.toList()); - // 총 투표수 계산 - long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - // 사용자가 선택한 후보의 선택률 계산 - userVotePercent = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - //1등 투표 계산 - // 투표수가 가장 많은 후보의 선택률 계산 - OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() - .mapToDouble(entry -> (double) entry.getValue() / totalVotes) - .max(); - - // 선택률이 가장 높은 후보의 ID들 찾기 - List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 - topCandidateList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - - topCandidatePercent = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - allCandidatePercent = post.getGeneralPoll().getCandidateList().stream() - .map(candidate -> { - Long candidateId = candidate.getId(); - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - - - return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(true) - .isVoted(true) - .postId(post.getId()) - .postVoteType(PostVoteType.GENERAL) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .title(post.getTitle()) - .content(post.getContent()) - .uploadDate(post.getCreatedAt()) - .pollOption(pollOptionDTOList) - .topCandidate(topCandidateList) - .userVote(userChoiceList) - .userVotePercent(userVotePercent) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .build(); - - } - - // 총 투표수 계산 - long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - - //1등 투표 계산 - // 투표수가 가장 많은 후보의 선택률 계산 - OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() - .mapToDouble(entry -> (double) entry.getValue() / totalVotes) - .max(); - - // 선택률이 가장 높은 후보의 ID들 찾기 - List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 - topCandidateList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - - topCandidatePercent = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - allCandidatePercent = post.getGeneralPoll().getCandidateList().stream() - .map(candidate -> { - Long candidateId = candidate.getId(); - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); + long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGeneralPoll().getDeadline()); + Boolean voteOnGoing = nanosUntilDeadline > 0; - return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(true) - .isVoted(false) - .postId(post.getId()) - .postVoteType(PostVoteType.GENERAL) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .title(post.getTitle()) - .content(post.getContent()) - .uploadDate(post.getCreatedAt()) - .pollOption(pollOptionDTOList) - .topCandidate(topCandidateList) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .build(); - } -//일반 투표 마감 후 + List pollOptionDTOList = post.getGeneralPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(cardVote -> cardVote.getUser().getId().equals(userId)) - .flatMap(cardVote -> cardVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getGeneralPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() - .filter(vote -> vote.getUser().getId().equals(userId)) - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.toList()); // 총 투표수 계산 long totalVotes = post.getGeneralPoll().getGeneralVoteList().stream() .flatMap(vote -> vote.getSelect_list().stream()) @@ -1095,13 +619,6 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Map candidateSelectionCounts = post.getGeneralPoll().getGeneralVoteList().stream() .flatMap(vote -> vote.getSelect_list().stream()) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - // 사용자가 선택한 후보의 선택률 계산 - userVotePercent = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); //1등 투표 계산 // 투표수가 가장 많은 후보의 선택률 계산 OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() @@ -1126,7 +643,6 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); - allCandidatePercent = post.getGeneralPoll().getCandidateList().stream() .map(candidate -> { Long candidateId = candidate.getId(); @@ -1134,33 +650,34 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); - if (engage) { - return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(false) - .isVoted(true) - .postId(post.getId()) - .postVoteType(PostVoteType.GENERAL) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .title(post.getTitle()) - .content(post.getContent()) - .uploadDate(post.getCreatedAt()) - .pollOption(pollOptionDTOList) - .topCandidate(topCandidateList) - .userVote(userChoiceList) - .userVotePercent(userVotePercent) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .build(); + if (engage) { + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); + Set selectedOptionIds = post.getGeneralPoll().getGeneralVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getGeneralPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + isVoted = true; } + return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(false) - .isVoted(false) + .onGoing(voteOnGoing) + .isVoted(isVoted) .postId(post.getId()) .postVoteType(PostVoteType.GENERAL) .nickname(post.getUser().getNickname()) @@ -1170,6 +687,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .uploadDate(post.getCreatedAt()) .pollOption(pollOptionDTOList) .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) .like(likeCount) @@ -1178,81 +697,24 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .isComment(isComment) .build(); - } + //게이지 투표 if (post.getVoteType() == PostVoteType.GAUGE) { if (!post.getGaugePoll().getGaugeVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { engage = true; } + long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getGaugePoll().getDeadline()); + Boolean voteOnGoing = nanosUntilDeadline > 0; + Integer userGauge = null; Optional userGaugeVoteOptional = post.getGaugePoll().getGaugeVoteList().stream() .filter(gaugeVote -> gaugeVote.getUser().getId().equals(userId)) .findFirst(); - Integer userGauge = null; if (userGaugeVoteOptional.isPresent()) { userGauge = userGaugeVoteOptional.get().getValue(); } - if (post.getGaugePoll().getDeadline().isAfter(LocalDateTime.now())) { - if (engage) { - - return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(true) - .isVoted(true) - .postId(post.getId()) - .postVoteType(PostVoteType.GAUGE) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .title(post.getTitle()) - .content(post.getContent()) - .uploadDate(post.getCreatedAt()) - .pollTitle(post.getGaugePoll().getPollTitle()) - .userGauge(userGauge) - .totalGauge(post.getGaugePoll().getGauge()) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .build(); - } - return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(true) - .isVoted(false) - .postId(post.getId()) - .postVoteType(PostVoteType.GAUGE) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .title(post.getTitle()) - .content(post.getContent()) - .uploadDate(post.getCreatedAt()) - .pollTitle(post.getGaugePoll().getPollTitle()) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .build(); - } - if (engage) { - return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(false) - .isVoted(true) - .postId(post.getId()) - .postVoteType(PostVoteType.GAUGE) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .title(post.getTitle()) - .content(post.getContent()) - .uploadDate(post.getCreatedAt()) - .pollTitle(post.getGaugePoll().getPollTitle()) - .userGauge(userGauge) - .totalGauge(post.getGaugePoll().getGauge()) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .build(); - } return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(false) - .isVoted(false) + .onGoing(voteOnGoing) + .isVoted(engage) .postId(post.getId()) .postVoteType(PostVoteType.GAUGE) .nickname(post.getUser().getNickname()) @@ -1261,185 +723,25 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .content(post.getContent()) .uploadDate(post.getCreatedAt()) .pollTitle(post.getGaugePoll().getPollTitle()) + .userGauge(userGauge) .totalGauge(post.getGaugePoll().getGauge()) .like(likeCount) .comment(commentCount) .isLike(isLike) .isComment(isComment) .build(); - } - List pollOptionDTOList = post.getCardPoll().getCandidateList().stream() - .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); + +//카드 투표 마감 전 if (!post.getCardPoll().getCardVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { engage = true; } -//카드 투표 마감 전 - if (post.getCardPoll().getDeadline().isAfter(LocalDateTime.now())) { - if (engage) { - //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() - .filter(cardVote -> cardVote.getUser().getId().equals(userId)) - .flatMap(cardVote -> cardVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getCardPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() - .filter(vote -> vote.getUser().getId().equals(userId)) - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.toList()); - // 총 투표수 계산 - long totalVotes = post.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - // 사용자가 선택한 후보의 선택률 계산 - userVotePercent = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - //1등 투표 계산 - // 투표수가 가장 많은 후보의 선택률 계산 - OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() - .mapToDouble(entry -> (double) entry.getValue() / totalVotes) - .max(); - - // 선택률이 가장 높은 후보의 ID들 찾기 - List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 - topCandidateList = post.getCardPoll().getCandidateList().stream() - .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - - topCandidatePercent = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - - allCandidatePercent = post.getCardPoll().getCandidateList().stream() - .map(candidate -> { - Long candidateId = candidate.getId(); - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - - return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(true) - .isVoted(true) - .postId(post.getId()) - .postVoteType(PostVoteType.CARD) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .title(post.getTitle()) - .content(post.getContent()) - .uploadDate(post.getCreatedAt()) - .pollOption(pollOptionDTOList) - .topCandidate(topCandidateList) - .userVote(userChoiceList) - .userVotePercent(userVotePercent) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .build(); - - } - - // 총 투표수 계산 - long totalVotes = post.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .count(); - // 각 후보별 선택된 횟수 계산 - Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - - //1등 투표 계산 - // 투표수가 가장 많은 후보의 선택률 계산 - OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() - .mapToDouble(entry -> (double) entry.getValue() / totalVotes) - .max(); - - // 선택률이 가장 높은 후보의 ID들 찾기 - List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 - topCandidateList = post.getCardPoll().getCandidateList().stream() - .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - - topCandidatePercent = mostVotedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); - - allCandidatePercent = post.getCardPoll().getCandidateList().stream() - .map(candidate -> { - Long candidateId = candidate.getId(); - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); + long nanosUntilDeadline = ChronoUnit.NANOS.between(now, post.getCardPoll().getDeadline()); + Boolean voteOnGoing = nanosUntilDeadline > 0; - return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(true) - .isVoted(false) - .postId(post.getId()) - .postVoteType(PostVoteType.CARD) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .title(post.getTitle()) - .content(post.getContent()) - .uploadDate(post.getCreatedAt()) - .pollOption(pollOptionDTOList) - .topCandidate(topCandidateList) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .build(); - } -//카드 투표 마감 후 + List pollOptionDTOList = post.getCardPoll().getCandidateList().stream() + .map(PostConverter::toPollOptionResDTO).collect(Collectors.toList()); //투표한 후보에 대한 정보 - Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() - .filter(cardVote -> cardVote.getUser().getId().equals(userId)) - .flatMap(cardVote -> cardVote.getSelect_list().stream()) - .collect(Collectors.toSet()); - userChoiceList = post.getCardPoll().getCandidateList().stream() - .filter(candidate -> selectedOptionIds.contains(candidate.getId())) - .map(PostConverter::toPollOptionResDTO) - .collect(Collectors.toList()); - // 사용자가 투표한 후보의 ID - List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() - .filter(vote -> vote.getUser().getId().equals(userId)) - .flatMap(vote -> vote.getSelect_list().stream()) - .collect(Collectors.toList()); // 총 투표수 계산 long totalVotes = post.getCardPoll().getCardVoteList().stream() .flatMap(vote -> vote.getSelect_list().stream()) @@ -1448,22 +750,15 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, Map candidateSelectionCounts = post.getCardPoll().getCardVoteList().stream() .flatMap(vote -> vote.getSelect_list().stream()) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - // 사용자가 선택한 후보의 선택률 계산 - userVotePercent = userSelectedCandidateIds.stream() - .map(candidateId -> { - long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); - return (int) ((double) selectionCount / totalVotes * 100); - }) - .collect(Collectors.toList()); //1등 투표 계산 // 투표수가 가장 많은 후보의 선택률 계산 - OptionalDouble highestCandidate = candidateSelectionCounts.entrySet().stream() + OptionalDouble hightestCandidate = candidateSelectionCounts.entrySet().stream() .mapToDouble(entry -> (double) entry.getValue() / totalVotes) .max(); // 선택률이 가장 높은 후보의 ID들 찾기 List mostVotedCandidateIds = candidateSelectionCounts.entrySet().stream() - .filter(entry -> entry.getValue() == highestCandidate.getAsDouble() * totalVotes) + .filter(entry -> entry.getValue() == hightestCandidate.getAsDouble() * totalVotes) .map(Map.Entry::getKey) .collect(Collectors.toList()); @@ -1479,7 +774,6 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); - allCandidatePercent = post.getCardPoll().getCandidateList().stream() .map(candidate -> { Long candidateId = candidate.getId(); @@ -1487,33 +781,34 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); - if (engage) { - return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(false) - .isVoted(true) - .postId(post.getId()) - .postVoteType(PostVoteType.CARD) - .nickname(post.getUser().getNickname()) - .userImg(userImg) - .title(post.getTitle()) - .content(post.getContent()) - .uploadDate(post.getCreatedAt()) - .pollOption(pollOptionDTOList) - .topCandidate(topCandidateList) - .userVote(userChoiceList) - .userVotePercent(userVotePercent) - .topCandidatePercent(topCandidatePercent) - .allCandidatePercent(allCandidatePercent) - .like(likeCount) - .comment(commentCount) - .isLike(isLike) - .isComment(isComment) - .build(); + if (engage) { + // 사용자가 투표한 후보의 ID + List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() + .filter(vote -> vote.getUser().getId().equals(userId)) + .flatMap(vote -> vote.getSelect_list().stream()) + .collect(Collectors.toList()); + Set selectedOptionIds = post.getCardPoll().getCardVoteList().stream() + .filter(cardVote -> cardVote.getUser().getId().equals(userId)) + .flatMap(cardVote -> cardVote.getSelect_list().stream()) + .collect(Collectors.toSet()); + userChoiceList = post.getCardPoll().getCandidateList().stream() + .filter(candidate -> selectedOptionIds.contains(candidate.getId())) + .map(PostConverter::toPollOptionResDTO) + .collect(Collectors.toList()); + // 사용자가 선택한 후보의 선택률 계산 + userVotePercent = userSelectedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return (int) ((double) selectionCount / totalVotes * 100); + }) + .collect(Collectors.toList()); + isVoted = true; } + return PostResponseDTO.PollPostGetResponse.builder() - .onGoing(false) - .isVoted(false) + .onGoing(voteOnGoing) + .isVoted(isVoted) .postId(post.getId()) .postVoteType(PostVoteType.CARD) .nickname(post.getUser().getNickname()) @@ -1523,6 +818,8 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .uploadDate(post.getCreatedAt()) .pollOption(pollOptionDTOList) .topCandidate(topCandidateList) + .userVote(userChoiceList) + .userVotePercent(userVotePercent) .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) .like(likeCount) @@ -1530,6 +827,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .isLike(isLike) .isComment(isComment) .build(); + } public static PostResponseDTO.PollPostGetListDTO pollPostGetListDTO(Page postList, Long userId) { @@ -1562,6 +860,7 @@ public static ParentPostDTO.ParentPostGetListDTO parentPostGetListDTO(Page .isEnd(postList.isLast()) .build(); } + public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post post, Long userId) { Integer likeCount = post.getPostLikeList().size(); Integer commentCount = post.getCommentList().size(); @@ -1570,7 +869,7 @@ public static PostResponseDTO.ReviewPostGetResponse reviewPostGetResponse(Post p File userFile = null; String userImg = null; Optional userFileOptional = Optional.ofNullable(post.getUser().getFile()); - Post parentPost= post.getParentPost(); + Post parentPost = post.getParentPost(); if (userFileOptional.isPresent()) { userFile = userFileOptional.get(); From 04ede319b51807d1850fc02c94505b0443c905ff Mon Sep 17 00:00:00 2001 From: hjh Date: Sun, 10 Mar 2024 15:47:54 +0900 Subject: [PATCH 238/255] =?UTF-8?q?#189=20=EC=A0=84=EC=B2=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=EC=8B=9C=20mypost,=20topVoteResult?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 27 ++++++++++++++++++- .../spring/web/dto/PostResponseDTO.java | 3 +++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 45d6ed2..091ad7e 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -585,6 +585,12 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, List userVotePercent = null; List topCandidatePercent = null; List allCandidatePercent = null; + List topVoteResult = null; + Boolean myPost=false; + if (post.getUser().getId().equals(userId)) { + myPost = true; + } + if (userFileOptional.isPresent()) { userFile = userFileOptional.get(); @@ -651,6 +657,13 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, }) .collect(Collectors.toList()); + topVoteResult = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); + if (engage) { // 사용자가 투표한 후보의 ID List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() @@ -676,6 +689,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, } return PostResponseDTO.PollPostGetResponse.builder() + .myPost(myPost) .onGoing(voteOnGoing) .isVoted(isVoted) .postId(post.getId()) @@ -691,6 +705,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .userVotePercent(userVotePercent) .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) + .topVoteResult(topVoteResult) .like(likeCount) .comment(commentCount) .isLike(isLike) @@ -713,6 +728,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, userGauge = userGaugeVoteOptional.get().getValue(); } return PostResponseDTO.PollPostGetResponse.builder() + .myPost(myPost) .onGoing(voteOnGoing) .isVoted(engage) .postId(post.getId()) @@ -732,7 +748,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .build(); } -//카드 투표 마감 전 +//카드 투표 if (!post.getCardPoll().getCardVoteList().stream().filter(cardVote -> cardVote.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty()) { engage = true; } @@ -781,6 +797,12 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); + topVoteResult = mostVotedCandidateIds.stream() + .map(candidateId -> { + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); if (engage) { // 사용자가 투표한 후보의 ID @@ -803,10 +825,12 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); + isVoted = true; } return PostResponseDTO.PollPostGetResponse.builder() + .myPost(myPost) .onGoing(voteOnGoing) .isVoted(isVoted) .postId(post.getId()) @@ -822,6 +846,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .userVotePercent(userVotePercent) .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) + .topVoteResult(topVoteResult) .like(likeCount) .comment(commentCount) .isLike(isLike) diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 597b4e8..9c89b57 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -2,6 +2,7 @@ import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; +import io.swagger.models.auth.In; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -73,6 +74,7 @@ public static class PollPostGetListDTO { @NoArgsConstructor @AllArgsConstructor public static class PollPostGetResponse { + Boolean myPost; Boolean onGoing; Boolean isVoted; Long postId; @@ -88,6 +90,7 @@ public static class PollPostGetResponse { List userVotePercent; List topCandidatePercent; List allCandidatePercent; + List topVoteResult; String pollTitle; //게이지투표만 해당(게이지 투표 이름) Integer userGauge; Integer totalGauge; From eab92778756016ea0a8136cd8638d6450ec5f695 Mon Sep 17 00:00:00 2001 From: hjh Date: Sun, 10 Mar 2024 21:13:04 +0900 Subject: [PATCH 239/255] =?UTF-8?q?#191=20=EC=A0=84=EC=B2=B4,=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20allCandidateResult=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 36 ++++++++++++++++++- .../spring/web/dto/PostResponseDTO.java | 2 ++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 091ad7e..5ef2d5b 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -252,6 +252,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B List userVotePercent = null; List topCandidatePercent = null; List allCandidatePercent = null; + List allCandidateResult=null; List userVoteResult = null; List topVoteResult = null; Integer userGauge = null; @@ -362,6 +363,13 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); + allCandidateResult = post.getGeneralPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId = candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); if (engage) { // 사용자가 투표한 후보의 ID List userSelectedCandidateIds = post.getGeneralPoll().getGeneralVoteList().stream() @@ -443,6 +451,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .userVote(userChoiceList) .userVotePercent(userVotePercent) .userVoteResult(userVoteResult) + .allCandidateResult(allCandidateResult) .topVoteResult(topVoteResult) .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) @@ -482,6 +491,13 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); + allCandidateResult = post.getCardPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId = candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); if (engage) { // 사용자가 투표한 후보의 ID List userSelectedCandidateIds = post.getCardPoll().getCardVoteList().stream() @@ -563,6 +579,7 @@ public static PostResponseDTO.PostDetailResponse postDetailResponse(Post post, B .userVote(userChoiceList) .userVotePercent(userVotePercent) .userVoteResult(userVoteResult) + .allCandidateResult(allCandidateResult) .topVoteResult(topVoteResult) .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) @@ -586,6 +603,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, List topCandidatePercent = null; List allCandidatePercent = null; List topVoteResult = null; + List allCandidateResult=null; Boolean myPost=false; if (post.getUser().getId().equals(userId)) { myPost = true; @@ -637,7 +655,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .map(Map.Entry::getKey) .collect(Collectors.toList()); - // 가장 높은 투표를 받은 후보들을 userChoiceList에 담기 + // 가장 높은 투표를 받은 후보들을 topCandidateList에 담기 topCandidateList = post.getGeneralPoll().getCandidateList().stream() .filter(candidate -> mostVotedCandidateIds.contains(candidate.getId())) .map(PostConverter::toPollOptionResDTO) @@ -656,6 +674,13 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); + allCandidateResult = post.getGeneralPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId = candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); topVoteResult = mostVotedCandidateIds.stream() .map(candidateId -> { @@ -705,6 +730,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .userVotePercent(userVotePercent) .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) + .allCandidateResult(allCandidateResult) .topVoteResult(topVoteResult) .like(likeCount) .comment(commentCount) @@ -797,6 +823,13 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, return (int) ((double) selectionCount / totalVotes * 100); }) .collect(Collectors.toList()); + allCandidateResult = post.getCardPoll().getCandidateList().stream() + .map(candidate -> { + Long candidateId = candidate.getId(); + long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); + return String.format("%d/%d", selectionCount, totalVotes); + }) + .collect(Collectors.toList()); topVoteResult = mostVotedCandidateIds.stream() .map(candidateId -> { long selectionCount = candidateSelectionCounts.getOrDefault(candidateId, 0L); @@ -846,6 +879,7 @@ public static PostResponseDTO.PollPostGetResponse pollPostGetResponse(Post post, .userVotePercent(userVotePercent) .topCandidatePercent(topCandidatePercent) .allCandidatePercent(allCandidatePercent) + .allCandidateResult(allCandidateResult) .topVoteResult(topVoteResult) .like(likeCount) .comment(commentCount) diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 9c89b57..4b2e351 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -46,6 +46,7 @@ public static class PostDetailResponse { List topCandidatePercent; List allCandidatePercent; List userVoteResult; // 투표글에서 사용자가 투표 완료시 투표인원/총인원 + List allCandidateResult; List topVoteResult; Integer userGauge; // 게이지 투표글에서만 사용, 후기글에서는 null Integer totalGauge; @@ -90,6 +91,7 @@ public static class PollPostGetResponse { List userVotePercent; List topCandidatePercent; List allCandidatePercent; + List allCandidateResult; List topVoteResult; String pollTitle; //게이지투표만 해당(게이지 투표 이름) Integer userGauge; From c4977cf1d600c60f97d89c2982616472f8618327 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 19 Mar 2024 14:57:49 +0900 Subject: [PATCH 240/255] =?UTF-8?q?#193=20Refactor:=20=EB=8B=B5=EB=B3=80?= =?UTF-8?q?=EC=9D=84=20=EA=B8=B0=EB=8B=A4=EB=A6=AC=EB=8A=94=20=EA=B3=A0?= =?UTF-8?q?=EB=AF=BC=EB=93=A4=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/repository/PostRepository.java | 31 +++++++++++++++++++ .../spring/service/PostServiceImpl.java | 20 +++++++----- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index 442be11..567463c 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -28,4 +28,35 @@ public interface PostRepository extends JpaRepository { @Query(value = "SELECT p FROM Post p JOIN p.postScrapList s JOIN p.category c WHERE s.user.id = :userId and c.id = :categoryId") Page findCategoryDetail(Long userId, Long categoryId, PageRequest pageRequest); + + @Query("SELECT p FROM Post p " + + "LEFT JOIN General_poll gp ON p.generalPoll.id = gp.id " + + "LEFT JOIN Gauge_poll ggp ON p.gaugePoll.id = ggp.id " + + "LEFT JOIN Card_poll cp ON p.cardPoll.id = cp.id " + + "WHERE p.postType = :vote " + + "AND p.state = :posting " + + "AND p.createdAt >= :minusDays " + + // 투표 마감 안 된 글들만 필터링 + "AND (" + + " (gp.deadline >= CURRENT_TIMESTAMP AND ggp.deadline IS NULL AND cp.deadline IS NULL) OR " + + " (gp.deadline IS NULL AND ggp.deadline >= CURRENT_TIMESTAMP AND cp.deadline IS NULL) OR " + + " (gp.deadline IS NULL AND ggp.deadline IS NULL AND cp.deadline >= CURRENT_TIMESTAMP)" + + ") " + + // 로그인한 사용자가 투표 안 한 글들만 필터링 + "AND (" + + " gp.id NOT IN (SELECT gv.generalPoll.id FROM General_vote gv WHERE gv.user.id = :userId) OR " + + " ggp.id NOT IN (SELECT gv.gaugePoll.id FROM Gauge_vote gv WHERE gv.user.id = :userId) OR " + + " cp.id NOT IN (SELECT gv.cardPoll.id FROM Card_vote gv WHERE gv.user.id = :userId)" + + ") " + + //각 투표 유형에 대한 투표 수를 합산해(어차피 하나에만 값이 있음) 투표 수가 적은 순으로 정렬 + "ORDER BY (" + + " (SELECT COUNT(gv.id) FROM General_vote gv WHERE gv.generalPoll.id = gp.id) + " + + " (SELECT COUNT(gv.id) FROM Gauge_vote gv WHERE gv.gaugePoll.id = ggp.id) + " + + " (SELECT COUNT(gv.id) FROM Card_vote gv WHERE gv.cardPoll.id = cp.id)" + + ") ASC") + Page findPostsOrderByVoteCount(@Param("vote") PostType vote, + @Param("posting") PostState posting, + @Param("minusDays") LocalDateTime minusDays, + @Param("userId") Long userId, + Pageable pageable); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index d29f477..1937580 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -411,15 +411,21 @@ public PostResponseDTO.PollPostGetListDTO getBestPosts(Integer page, Integer siz @Override public PostResponseDTO.PollPostGetListDTO getRecentPosts(Integer page, Integer size, HttpServletRequest request) { Long userId = jwtTokenProvider.getCurrentUser(request); - Optional optionalUser = userRepository.findById(userId); - if (optionalUser.isEmpty()) { - userService.checkUser(false); - } + User user = userRepository.findById(userId) + .orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); + + LocalDateTime minusDays = LocalDateTime.now().minusDays(7); // 7일 이내(임시) + Pageable pageable = PageRequest.of(page, size); + Page recentPostPage = postRepository.findPostsOrderByVoteCount(PostType.VOTE, PostState.POSTING, minusDays, user.getId(), pageable); - Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); - Page recentPostPage = postRepository.findByPostTypeAndState(PostType.VOTE, PostState.POSTING, pageable); + // 랜덤으로 섞기 + List postList = new ArrayList<>(recentPostPage.getContent()); + // 리스트를 랜덤하게 섞기 + Collections.shuffle(postList); + // 섞인 리스트를 페이지로 다시 변환 + Page shuffledPage = new PageImpl<>(postList, recentPostPage.getPageable(), postList.size()); - return PostConverter.pollPostGetListDTO(recentPostPage, userId); + return PostConverter.pollPostGetListDTO(shuffledPage, userId); } @Override From aefbbd9de5de26d516289fef180e550093cc96f5 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Tue, 19 Mar 2024 15:26:29 +0900 Subject: [PATCH 241/255] =?UTF-8?q?#193=20Refactor:=20=EB=8B=B5=EB=B3=80?= =?UTF-8?q?=EC=9D=84=20=EA=B8=B0=EB=8B=A4=EB=A6=AC=EB=8A=94=20=EA=B3=A0?= =?UTF-8?q?=EB=AF=BC=EB=93=A4=20-=20=ED=88=AC=ED=91=9C=20=EB=A7=88?= =?UTF-8?q?=EA=B0=90=20=EC=95=88=20=EB=90=9C=20=EA=B8=80=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=EB=A7=81=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/repository/PostRepository.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index 567463c..3dde811 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -38,9 +38,9 @@ public interface PostRepository extends JpaRepository { "AND p.createdAt >= :minusDays " + // 투표 마감 안 된 글들만 필터링 "AND (" + - " (gp.deadline >= CURRENT_TIMESTAMP AND ggp.deadline IS NULL AND cp.deadline IS NULL) OR " + - " (gp.deadline IS NULL AND ggp.deadline >= CURRENT_TIMESTAMP AND cp.deadline IS NULL) OR " + - " (gp.deadline IS NULL AND ggp.deadline IS NULL AND cp.deadline >= CURRENT_TIMESTAMP)" + + " (gp.VoteOnGoing = true) OR " + + " (ggp.VoteOnGoing = true) OR " + + " (cp.VoteOnGoing = true)" + ") " + // 로그인한 사용자가 투표 안 한 글들만 필터링 "AND (" + From 271b5db4bdc6e1c38775e3ea5acd9447ad4527ad Mon Sep 17 00:00:00 2001 From: MinYeongPark Date: Tue, 19 Mar 2024 19:04:55 +0900 Subject: [PATCH 242/255] =?UTF-8?q?Docs:=20README=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8851782..2f1a180 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,43 @@ -# BE <고민친구> +# 🗳️ 고민친구 +
-### 커밋 규칙 +고민친구 백엔드 리포지토리 + +
+ +## 🧑‍🤝‍🧑 프로젝트 개요 +투표 기반 의사결정 지원 웹 서비스 + +
+
+ + + +## 🔎 주요 기능 +- 로그인 / 회원가입 +- 고민 투표 & 고민 후기 글/댓글 관리 +- 마이페이지 내 정보 관리 +- 댓글 작성 및 투표 마감 실시간 알림 + +
+ +## 🔭 기술 스택 +- Java, Springboot +- AWS EB, ElastiCache(Redis), RDS, VPC +- Spring Security +- SSE 실시간 알림 + +
+ +## 👨‍👩‍👧‍👦 팀원 소개 +- PM 1명 +- Design 1명 +- Front-End(Web) 4명 +- Back-End 4명 + +
+ +## 📖 커밋 규칙 #{이슈번호} {type}: [작업한 내용] @@ -12,7 +49,6 @@ ex) #200 Feat: 사용자 뮤트 기능 추가 | Feat | 새로운 기능 추가 | | Fix | 버그 수정 | | Docs | 문서 수정 | -| Docs | 문서 수정 | | Style | 코드 formatting, 세미콜론 누락, 코드 자체의 변경이 없는 경우 | | Refactor | 코드 리팩토링 | | Test | 테스트 코드, 리팩토링 테스트 코드 추가 | @@ -22,4 +58,4 @@ ex) #200 Feat: 사용자 뮤트 기능 추가 | Rename | 파일 또는 폴더 명을 수정하거나 옮기는 작업만인 경우 | | Remove | 파일을 삭제하는 작업만 수행한 경우 | | !BREAKING CHANGE | 커다란 API 변경의 경우 | -| !HOTFIX | 급하게 치명적인 버그를 고쳐야 하는 경우 | \ No newline at end of file +| !HOTFIX | 급하게 치명적인 버그를 고쳐야 하는 경우 | From ee964999532c9a13470dc5ea35cf27c38d70e561 Mon Sep 17 00:00:00 2001 From: MinYeongPark Date: Tue, 19 Mar 2024 19:07:10 +0900 Subject: [PATCH 243/255] =?UTF-8?q?Docs:=20README=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2f1a180..db72cef 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # 🗳️ 고민친구 -
+
고민친구 백엔드 리포지토리 @@ -8,8 +8,8 @@ ## 🧑‍🤝‍🧑 프로젝트 개요 투표 기반 의사결정 지원 웹 서비스 -
-
+
+
From d2c252aee42563d8e0123cdfc992999b2a80f223 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 2 Jun 2024 16:32:12 +0900 Subject: [PATCH 244/255] =?UTF-8?q?#195=20Feat:=20=EA=B8=80=20=EC=8B=A0?= =?UTF-8?q?=EA=B3=A0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 4 ++- .../spring/converter/PostConverter.java | 17 +++++++++++ .../java/friend/spring/domain/Report.java | 12 +++----- .../friend/spring/domain/ReportCategory.java | 29 ++++++++++++++++++ .../spring/domain/enums/ReportCategory.java | 5 ---- .../repository/ReportCategoryRepository.java | 10 +++++++ .../spring/repository/ReportRepository.java | 11 +++++++ .../friend/spring/service/PostService.java | 3 ++ .../spring/service/PostServiceImpl.java | 30 +++++++++++++++++++ .../web/controller/PostRestController.java | 26 ++++++++++++++++ .../friend/spring/web/dto/PostRequestDTO.java | 7 +++++ .../spring/web/dto/PostResponseDTO.java | 8 +++++ 12 files changed, 148 insertions(+), 14 deletions(-) create mode 100644 src/main/java/friend/spring/domain/ReportCategory.java delete mode 100644 src/main/java/friend/spring/domain/enums/ReportCategory.java create mode 100644 src/main/java/friend/spring/repository/ReportCategoryRepository.java create mode 100644 src/main/java/friend/spring/repository/ReportRepository.java diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index a9bd165..495c02d 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -61,7 +61,9 @@ POST_SCRAP_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4015", "글에 대한 스크랩 데이터가 이미 존재합니다."), DEADLINE_OVER(HttpStatus.BAD_REQUEST, "POST4016", "투표 마감 시간이 지났습니다"), ALREADY_VOTE(HttpStatus.BAD_REQUEST, "POST4017", "이미 투표 하셨습니다."), -// USER_VOTE(HttpStatus.BAD_REQUEST,"POST4017","작성자는 투표가 불가능 합니다 하셨습니다."), +// USER_VOTE(HttpStatus.BAD_REQUEST,"POST4017","작성자는 투표가 불가능 합니다 하셨습니다."), // 이거 필요없으면 지워야 할 것 같습니다! + + POST_REPORT_DUPLICATE(HttpStatus.BAD_REQUEST, "POST4018", "이 유저가 해당 글을 신고한 신고 내역 데이터가 이미 존재합니다."), // 댓글 관련 응답 COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "COMMENT4001", "댓글을 찾을 수 없습니다."), diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 5ef2d5b..f6c45fc 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -4,6 +4,7 @@ import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; +import friend.spring.domain.enums.ReportType; import friend.spring.service.PostQueryService; import friend.spring.web.dto.*; import org.springframework.data.domain.Page; @@ -995,6 +996,22 @@ public static PostResponseDTO.ScrapCreateRes toScrapCreateRes(Post_scrap post_sc .post_scrap_id(post_scrap.getId()) .build(); } + + public static Report toReportPost(Post post, User user, ReportCategory reportCategory) { + return Report.builder() + .targetType(ReportType.POST) + .targetId(post.getId()) + .reportCategory(reportCategory) + .user(user) + .build(); + } + + public static PostResponseDTO.PostReportRes toPostReportRes(Report report) { + return PostResponseDTO.PostReportRes.builder() + .reportId(report.getId()) + .build(); + } + } diff --git a/src/main/java/friend/spring/domain/Report.java b/src/main/java/friend/spring/domain/Report.java index cf87d47..396f4fd 100644 --- a/src/main/java/friend/spring/domain/Report.java +++ b/src/main/java/friend/spring/domain/Report.java @@ -1,7 +1,6 @@ package friend.spring.domain; import friend.spring.domain.common.BaseEntity; -import friend.spring.domain.enums.ReportCategory; import friend.spring.domain.enums.ReportType; import lombok.*; @@ -22,14 +21,11 @@ public class Report extends BaseEntity { private ReportType targetType; @Column(nullable = false) - private Integer targetId; + private Long targetId; - @Column(nullable = false, length = 500) - private String content; - - @Enumerated(EnumType.STRING) - @Column - private ReportCategory category; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "report_category_id") + private ReportCategory reportCategory; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") diff --git a/src/main/java/friend/spring/domain/ReportCategory.java b/src/main/java/friend/spring/domain/ReportCategory.java new file mode 100644 index 0000000..b382fd1 --- /dev/null +++ b/src/main/java/friend/spring/domain/ReportCategory.java @@ -0,0 +1,29 @@ +package friend.spring.domain; + +import friend.spring.domain.common.BaseEntity; +import lombok.*; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class ReportCategory { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String name; + + @Builder.Default + @OneToMany(mappedBy = "reportCategory") + private List reportList = new ArrayList<>(); + +} + diff --git a/src/main/java/friend/spring/domain/enums/ReportCategory.java b/src/main/java/friend/spring/domain/enums/ReportCategory.java deleted file mode 100644 index 1c79bbf..0000000 --- a/src/main/java/friend/spring/domain/enums/ReportCategory.java +++ /dev/null @@ -1,5 +0,0 @@ -package friend.spring.domain.enums; - -public enum ReportCategory { - SPAM, PRONO, NOT_FIT_POST, ABUSE, AD -} diff --git a/src/main/java/friend/spring/repository/ReportCategoryRepository.java b/src/main/java/friend/spring/repository/ReportCategoryRepository.java new file mode 100644 index 0000000..1487661 --- /dev/null +++ b/src/main/java/friend/spring/repository/ReportCategoryRepository.java @@ -0,0 +1,10 @@ +package friend.spring.repository; + +import friend.spring.domain.Category; +import friend.spring.domain.Report; +import friend.spring.domain.ReportCategory; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReportCategoryRepository extends JpaRepository { + ReportCategory findByName(String category); +} diff --git a/src/main/java/friend/spring/repository/ReportRepository.java b/src/main/java/friend/spring/repository/ReportRepository.java new file mode 100644 index 0000000..7991e22 --- /dev/null +++ b/src/main/java/friend/spring/repository/ReportRepository.java @@ -0,0 +1,11 @@ +package friend.spring.repository; + +import friend.spring.domain.Report; +import friend.spring.domain.enums.ReportType; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface ReportRepository extends JpaRepository { + Optional findByTargetTypeAndTargetIdAndUserId(ReportType post, Long postId, Long userId); +} diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index fc4034d..e242862 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -3,6 +3,7 @@ import friend.spring.domain.Candidate; import friend.spring.domain.Post; +import friend.spring.domain.Report; import friend.spring.domain.User; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; @@ -48,5 +49,7 @@ public interface PostService { Post_scrap createScrapPost(Long postId, HttpServletRequest request); void deleteScrapPost(Long postId, HttpServletRequest request); + + Report createReportPost(Long postId, PostRequestDTO.PostReportReq request, HttpServletRequest request2); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index d29f477..4dd8b2a 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -8,6 +8,7 @@ import friend.spring.domain.*; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; +import friend.spring.domain.enums.ReportType; import friend.spring.domain.enums.S3ImageType; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; @@ -42,6 +43,8 @@ public class PostServiceImpl implements PostService { private final Card_PollRepository cardPollRepository; private final PointRepository pointRepository; private final CategoryRepository categoryRepository; + private final ReportCategoryRepository reportCategoryRepository; + private final ReportRepository reportRepository; private final PostLikeRepository postLikeRepository; private final CommentRepository commentRepository; @@ -470,4 +473,31 @@ public void deleteScrapPost(Long postId, HttpServletRequest request) { postScrapRepository.delete(post_scrap); } + @Override + public Report createReportPost(Long postId, PostRequestDTO.PostReportReq request, HttpServletRequest request2) { + Long userId = jwtTokenProvider.getCurrentUser(request2); + + Optional optionalPost = postRepository.findById(postId); + if (optionalPost.isEmpty()) { + this.checkPost(false); + } + + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Post post = optionalPost.get(); + User user = optionalUser.get(); + + // 이미 신고된 건인지 확인 + Optional optionalReport = reportRepository.findByTargetTypeAndTargetIdAndUserId(ReportType.POST, postId, userId); + if (!optionalReport.isEmpty()) { + throw new PostHandler(POST_REPORT_DUPLICATE); + } + + ReportCategory reportCategory = reportCategoryRepository.findByName(request.getReportCategory()); + Report report = PostConverter.toReportPost(post, user, reportCategory); + return reportRepository.save(report); + } } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index c8ce789..746c972 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -5,6 +5,7 @@ import friend.spring.converter.PostConverter; import friend.spring.domain.Candidate; import friend.spring.domain.Post; +import friend.spring.domain.Report; import friend.spring.repository.PostRepository; import friend.spring.service.JwtTokenService; import friend.spring.service.PostQueryService; @@ -26,6 +27,8 @@ import javax.validation.Valid; import java.io.IOException; +import static friend.spring.apiPayload.code.status.ErrorStatus.POST_REPORT_DUPLICATE; + @RestController @RequiredArgsConstructor @Validated @@ -303,4 +306,27 @@ public ApiResponse deleteScrapPost( postService.deleteScrapPost(postId, request); return ApiResponse.onSuccess(null); } + + // 글 신고 + @PostMapping("/posts/{post-id}/report") + @Operation(summary = "글 신고 API", description = "글 신고하는 API입니다. ex) /posts/1/report") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4018", description = "BAD_REQUEST, 이 유저가 해당 글을 신고한 신고 내역 데이터가 이미 존재합니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) + public ApiResponse createReportPost( + @PathVariable("post-id") Long postId, + @RequestBody PostRequestDTO.PostReportReq request, + @RequestHeader("atk") String atk, + HttpServletRequest request2 + ) { + Report postReport = postService.createReportPost(postId, request, request2); + return ApiResponse.onSuccess(PostConverter.toPostReportRes(postReport)); + } } diff --git a/src/main/java/friend/spring/web/dto/PostRequestDTO.java b/src/main/java/friend/spring/web/dto/PostRequestDTO.java index 6619638..d80a409 100644 --- a/src/main/java/friend/spring/web/dto/PostRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/PostRequestDTO.java @@ -50,4 +50,11 @@ public static class PostEditReq { Boolean voteOnGoing; } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class PostReportReq { + String reportCategory; + } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 4b2e351..acdf06d 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -158,4 +158,12 @@ public static class PostLikeRes { public static class ScrapCreateRes { Long post_scrap_id; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class PostReportRes { + Long reportId; + } } \ No newline at end of file From 35d5135e3f01982533299bbfcdd71ba21fda1845 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 2 Jun 2024 17:04:44 +0900 Subject: [PATCH 245/255] =?UTF-8?q?#195=20Feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=8B=A0=EA=B3=A0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiPayload/code/status/ErrorStatus.java | 1 + .../spring/converter/CommentConverter.java | 20 +++++++++-- .../friend/spring/service/CommentService.java | 3 ++ .../spring/service/CommentServiceImpl.java | 33 +++++++++++++++++++ .../web/controller/CommentRestController.java | 25 ++++++++++++++ .../spring/web/dto/CommentRequestDTO.java | 8 +++++ .../spring/web/dto/CommentResponseDTO.java | 8 +++++ 7 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 495c02d..698c9a5 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -73,6 +73,7 @@ COMMENT_NOT_CORRECT_USER(HttpStatus.BAD_REQUEST, "COMMENT4005", "올바른 사용자(댓글 작성자)가 아닙니다."), COMMENT_POST_NOT_MATCH(HttpStatus.BAD_REQUEST, "COMMENT4006", "해당 글에 작성된 댓글이 아닙니다."), COMMENT_LIKE_DUPLICATE(HttpStatus.BAD_REQUEST, "COMMENT4007", "댓글에 대한 좋아요 데이터가 이미 존재합니다."), + COMMENT_REPORT_DUPLICATE(HttpStatus.BAD_REQUEST, "COMMENT4008", "이 유저가 해당 댓글을 신고한 신고 내역 데이터가 이미 존재합니다."), // 알림 관련 응답 ALARM_NOT_FOUND(HttpStatus.NOT_FOUND, "ALARM4001", "알림이 없습니다"), diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index 97b6051..0478464 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -1,13 +1,13 @@ package friend.spring.converter; -import friend.spring.domain.Comment; -import friend.spring.domain.Post; -import friend.spring.domain.User; +import friend.spring.domain.*; import friend.spring.domain.enums.CommentState; +import friend.spring.domain.enums.ReportType; import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; +import friend.spring.web.dto.PostResponseDTO; import java.util.ArrayList; import java.util.List; @@ -116,4 +116,18 @@ public static CommentResponseDTO.myCommentRes toMyCommentResDTO(Comment comment) .build(); } + public static CommentResponseDTO.CommentReportRes toCommentReportRes(Report report) { + return CommentResponseDTO.CommentReportRes.builder() + .reportId(report.getId()) + .build(); + } + + public static Report toReportComment(Comment comment, User user, ReportCategory reportCategory) { + return Report.builder() + .targetType(ReportType.COMMENT) + .targetId(comment.getId()) + .reportCategory(reportCategory) + .user(user) + .build(); + } } diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index 3199432..2d9e309 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -1,6 +1,7 @@ package friend.spring.service; import friend.spring.domain.Comment; +import friend.spring.domain.Report; import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.web.dto.CommentRequestDTO; @@ -36,4 +37,6 @@ public interface CommentService { Page getMyCommentList(Long userId, Integer page); void deleteComment(Long postId, Long commentId, HttpServletRequest request); + + Report createReportComment(Long commentId, CommentRequestDTO.CommentReportReq request, HttpServletRequest request2); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 6863c52..5bacee6 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -3,11 +3,14 @@ import friend.spring.apiPayload.GeneralException; import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.apiPayload.handler.CommentHandler; +import friend.spring.apiPayload.handler.PostHandler; import friend.spring.converter.AlarmConverter; import friend.spring.converter.CommentConverter; +import friend.spring.converter.PostConverter; import friend.spring.converter.SseConverter; import friend.spring.domain.*; import friend.spring.domain.enums.AlarmType; +import friend.spring.domain.enums.ReportType; import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.repository.*; @@ -38,6 +41,8 @@ public class CommentServiceImpl implements CommentService { private final CommentChoiceRepository commentChoiceRepository; private final PointRepository pointRepository; private final AlarmRepository alarmRepository; + private final ReportRepository reportRepository; + private final ReportCategoryRepository reportCategoryRepository; private final UserService userService; private final PostService postService; private final JwtTokenProvider jwtTokenProvider; @@ -400,5 +405,33 @@ public void deleteComment(Long postId, Long commentId, HttpServletRequest reques } comment.updateStateToDeleted(); } + + @Override + public Report createReportComment(Long commentId, CommentRequestDTO.CommentReportReq request, HttpServletRequest request2) { + Long userId = jwtTokenProvider.getCurrentUser(request2); + + Optional optionalComment = commentRepository.findById(commentId); + if (optionalComment.isEmpty()) { + this.checkComment(false); + } + + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isEmpty()) { + userService.checkUser(false); + } + + Comment comment = optionalComment.get(); + User user = optionalUser.get(); + + // 이미 신고된 건인지 확인 + Optional optionalReport = reportRepository.findByTargetTypeAndTargetIdAndUserId(ReportType.COMMENT, commentId, userId); + if (!optionalReport.isEmpty()) { + throw new CommentHandler(COMMENT_REPORT_DUPLICATE); + } + + ReportCategory reportCategory = reportCategoryRepository.findByName(request.getReportCategory()); + Report report = CommentConverter.toReportComment(comment, user, reportCategory); + return reportRepository.save(report); + } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 583516c..534abc0 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -2,7 +2,9 @@ import friend.spring.apiPayload.ApiResponse; import friend.spring.converter.CommentConverter; +import friend.spring.converter.PostConverter; import friend.spring.domain.Comment; +import friend.spring.domain.Report; import friend.spring.domain.mapping.Comment_choice; import friend.spring.domain.mapping.Comment_like; import friend.spring.service.CommentService; @@ -197,4 +199,27 @@ public ApiResponse deleteComment( commentService.deleteComment(postId, commentId, request); return ApiResponse.onSuccess(null); } + + // 댓글 신고 + @PostMapping("/posts/{post-id}/comment/{comment-id}/report") + @Operation(summary = "댓글 신고 API", description = "댓글 신고하는 API입니다. ex) /posts/1/report") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4018", description = "BAD_REQUEST, 이 유저가 해당 글을 신고한 신고 내역 데이터가 이미 존재합니다."), + }) + @Parameters({ + @Parameter(name = "post-id", description = "path variable - 글 아이디"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) + public ApiResponse createReportComment( + @PathVariable("comment-id") Long commentId, + @RequestBody CommentRequestDTO.CommentReportReq request, + @RequestHeader("atk") String atk, + HttpServletRequest request2 + ) { + Report commentReport = commentService.createReportComment(commentId, request, request2); + return ApiResponse.onSuccess(CommentConverter.toCommentReportRes(commentReport)); + } } diff --git a/src/main/java/friend/spring/web/dto/CommentRequestDTO.java b/src/main/java/friend/spring/web/dto/CommentRequestDTO.java index 96e1ee7..82e9559 100644 --- a/src/main/java/friend/spring/web/dto/CommentRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentRequestDTO.java @@ -27,4 +27,12 @@ public static class commentEditReq { @NotBlank String content; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class CommentReportReq { + String reportCategory; + } } diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index 790d956..2726538 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -70,4 +70,12 @@ public static class myCommentRes { Integer commentLike; Integer reComment; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class CommentReportRes { + Long reportId; + } } From 23cc9760c37dbd66a74d39479149727c4222aff8 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sun, 2 Jun 2024 17:05:42 +0900 Subject: [PATCH 246/255] =?UTF-8?q?#196=20Feat=20:=20=EA=B8=80=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/converter/PostConverter.java | 36 +++++++++++++++++++ .../spring/repository/PostRepository.java | 3 ++ .../spring/service/PostQueryService.java | 2 ++ .../spring/service/PostQueryServiceImpl.java | 6 ++++ .../friend/spring/service/PostService.java | 2 +- .../web/controller/PostRestController.java | 19 ++++++++++ .../spring/web/dto/PostResponseDTO.java | 25 +++++++++++++ 7 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 45d6ed2..ebf1a92 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -936,6 +936,42 @@ public static PostResponseDTO.ScrapCreateRes toScrapCreateRes(Post_scrap post_sc .post_scrap_id(post_scrap.getId()) .build(); } + + public static PostResponseDTO.PostSearchRes PostSearchResDTO(Post post,Long userId) { + Integer likeCount = post.getPostLikeList().size(); + Integer commentCount = post.getCommentList().size(); + Boolean isLike = !post.getPostLikeList().stream().filter(like -> like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + Boolean isComment = !post.getCommentList().stream().filter(like -> like.getUser().getId().equals(userId)).collect(Collectors.toList()).isEmpty(); + File userFile = null; + String userImg = null; + Optional userFileOptional = Optional.ofNullable(post.getUser().getFile()); + + if (userFileOptional.isPresent()) { + userFile = userFileOptional.get(); + userImg = userFile.getUrl(); + } + return PostResponseDTO.PostSearchRes.builder() + .postId(post.getId()) + .nickname(post.getUser().getNickname()) + .userImg(userImg) + .title(post.getTitle()) + .content(post.getContent()) + .uploadDate(post.getCreatedAt()) + .like(likeCount) + .comment(commentCount) + .isLike(isLike) + .isComment(isComment) + .build(); + } + + public static PostResponseDTO.PostSearchList PostSearchListDTO(Page postList, Long userId) { + List postSearchLists = postList.stream() + .map(post -> PostSearchResDTO(post, userId)).collect(Collectors.toList()); + return PostResponseDTO.PostSearchList.builder() + .reviewPostList(postSearchLists) + .isEnd(postList.isLast()) + .build(); + } } diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index 442be11..df873e8 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -28,4 +28,7 @@ public interface PostRepository extends JpaRepository { @Query(value = "SELECT p FROM Post p JOIN p.postScrapList s JOIN p.category c WHERE s.user.id = :userId and c.id = :categoryId") Page findCategoryDetail(Long userId, Long categoryId, PageRequest pageRequest); + + @Query(value = "SELECT p FROM Post p WHERE p.title LIKE :search OR p.content LIKE :search") + Page findByKeyWord(String search, Pageable pageable); } diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index d2b7263..1c5822b 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -22,4 +22,6 @@ public interface PostQueryService { Page getReviewList(Integer page, Integer size, Integer arrange); Page getParentPostList(Integer page, Integer size, HttpServletRequest request); + Page getPostSearch(Integer page, Integer size, String search); + } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index aa55538..69a0115 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -143,4 +143,10 @@ public Page getParentPostList(Integer page, Integer size, HttpServletReque } + @Override + @Transactional + public Page getPostSearch(Integer page, Integer size, String search) { + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); + return postRepository.findByKeyWord(search, pageable); + } } diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index fc4034d..001553f 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -48,5 +48,5 @@ public interface PostService { Post_scrap createScrapPost(Long postId, HttpServletRequest request); void deleteScrapPost(Long postId, HttpServletRequest request); -} +} diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index c8ce789..f93aff4 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -303,4 +303,23 @@ public ApiResponse deleteScrapPost( postService.deleteScrapPost(postId, request); return ApiResponse.onSuccess(null); } + + @GetMapping("/post/search/") + @Operation(summary = "글 검색 API", description = "글을 검색합니다") + @Parameters({ + @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), + @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)"), + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + @Parameter(name = "search", description = "query string(RequestParam) - 검색어.") + }) + public ApiResponse getPostSearch(@RequestParam(name = "page", defaultValue = "0") Integer page, + @RequestParam(name = "size", defaultValue = "15") Integer size, + @RequestParam(name = "search") String search, + @RequestHeader("atk") String atk, + HttpServletRequest request2) { + Long userId = jwtTokenService.JwtToId(request2); + Page postPage = postQueryService.getPostSearch(page, size, search); + return ApiResponse.onSuccess(PostConverter.PostSearchListDTO(postPage, userId)); + + } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index 597b4e8..9c1b66c 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -153,4 +153,29 @@ public static class PostLikeRes { public static class ScrapCreateRes { Long post_scrap_id; } + + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class PostSearchList { + List reviewPostList; + private Boolean isEnd; + } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class PostSearchRes{ + Long postId; + String nickname; + String userImg; + String title; + String content; + LocalDateTime uploadDate; + Integer like; + Integer comment; + Boolean isLike; + Boolean isComment; + } } \ No newline at end of file From cacae0299bc29bc27b4f550298301d12f3d9d5eb Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sun, 2 Jun 2024 17:12:08 +0900 Subject: [PATCH 247/255] =?UTF-8?q?#196=20Feat=20:=20=EA=B8=80=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20API=20=EA=B5=AC=ED=98=84=20JPQL=20like=EB=AC=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/friend/spring/repository/PostRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/friend/spring/repository/PostRepository.java b/src/main/java/friend/spring/repository/PostRepository.java index df873e8..6932ecf 100644 --- a/src/main/java/friend/spring/repository/PostRepository.java +++ b/src/main/java/friend/spring/repository/PostRepository.java @@ -29,6 +29,6 @@ public interface PostRepository extends JpaRepository { @Query(value = "SELECT p FROM Post p JOIN p.postScrapList s JOIN p.category c WHERE s.user.id = :userId and c.id = :categoryId") Page findCategoryDetail(Long userId, Long categoryId, PageRequest pageRequest); - @Query(value = "SELECT p FROM Post p WHERE p.title LIKE :search OR p.content LIKE :search") + @Query(value = "SELECT p FROM Post p WHERE p.title LIKE CONCAT('%',:search,'%') OR p.content LIKE CONCAT('%',:search,'%')") Page findByKeyWord(String search, Pageable pageable); } From 94c0f47b8b84f800a9a93b6952eafd7205da084a Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 2 Jun 2024 18:52:20 +0900 Subject: [PATCH 248/255] =?UTF-8?q?#195=20Refactor:=20=EB=8C=93=EA=B8=80?= =?UTF-8?q?=20=EC=8B=A0=EA=B3=A0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/apiPayload/code/status/ErrorStatus.java | 4 +--- .../friend/spring/web/controller/CommentRestController.java | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java index 698c9a5..2daa04f 100644 --- a/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/friend/spring/apiPayload/code/status/ErrorStatus.java @@ -8,9 +8,7 @@ @Getter @AllArgsConstructor -public enum -ErrorStatus implements BaseErrorCode { - +public enum ErrorStatus implements BaseErrorCode { // 가장 일반적인 응답 _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON5000", "서버 에러, 관리자에게 문의 바랍니다."), diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 534abc0..9c46d91 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -207,7 +207,7 @@ public ApiResponse deleteComment( @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 요청에 성공했습니다."), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER4001", description = "NOT_FOUND, 사용자를 찾을 수 없습니다."), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4001", description = "NOT_FOUND, 글을 찾을 수 없습니다."), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST4018", description = "BAD_REQUEST, 이 유저가 해당 글을 신고한 신고 내역 데이터가 이미 존재합니다."), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMENT4008", description = "BAD_REQUEST, 이 유저가 해당 댓글을 신고한 신고 내역 데이터가 이미 존재합니다."), }) @Parameters({ @Parameter(name = "post-id", description = "path variable - 글 아이디"), From 72bb5831b80f0fb369b005de3c36611b75616ed4 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 2 Jun 2024 19:39:32 +0900 Subject: [PATCH 249/255] =?UTF-8?q?#195=20Refactor:=20ResponseDTO=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=A4=91=EB=B3=B5=EB=90=9C=20=EC=8B=A0?= =?UTF-8?q?=EA=B3=A0=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/spring/converter/CommentConverter.java | 6 ++++-- .../java/friend/spring/converter/PostConverter.java | 8 ++++---- .../java/friend/spring/service/CommentService.java | 3 ++- .../friend/spring/service/CommentServiceImpl.java | 13 ++++++++++--- .../java/friend/spring/service/PostService.java | 3 +-- .../java/friend/spring/service/PostServiceImpl.java | 12 +++++++++--- .../web/controller/CommentRestController.java | 3 ++- .../spring/web/controller/PostRestController.java | 5 +---- .../friend/spring/web/dto/CommentResponseDTO.java | 3 +++ .../java/friend/spring/web/dto/PostResponseDTO.java | 13 ++++++++++++- 10 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/main/java/friend/spring/converter/CommentConverter.java b/src/main/java/friend/spring/converter/CommentConverter.java index 0478464..40e5efe 100644 --- a/src/main/java/friend/spring/converter/CommentConverter.java +++ b/src/main/java/friend/spring/converter/CommentConverter.java @@ -116,9 +116,11 @@ public static CommentResponseDTO.myCommentRes toMyCommentResDTO(Comment comment) .build(); } - public static CommentResponseDTO.CommentReportRes toCommentReportRes(Report report) { + public static CommentResponseDTO.CommentReportRes toCommentReportRes(PostResponseDTO.ReportResult reportResult) { return CommentResponseDTO.CommentReportRes.builder() - .reportId(report.getId()) + .reportId(reportResult.getReport().getId()) + .createdAt(reportResult.getReport().getCreatedAt()) + .duplicatedReport(reportResult.getDuplicatedReport()) .build(); } diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index f6c45fc..5ed5b47 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -20,10 +20,8 @@ import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; -import friend.spring.web.dto.CandidateResponseDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; -import software.amazon.awssdk.services.s3.endpoints.internal.Value; import java.util.List; @@ -1006,9 +1004,11 @@ public static Report toReportPost(Post post, User user, ReportCategory reportCat .build(); } - public static PostResponseDTO.PostReportRes toPostReportRes(Report report) { + public static PostResponseDTO.PostReportRes toPostReportRes(PostResponseDTO.ReportResult reportResult) { return PostResponseDTO.PostReportRes.builder() - .reportId(report.getId()) + .reportId(reportResult.getReport().getId()) + .createdAt(reportResult.getReport().getCreatedAt()) + .duplicatedReport(reportResult.getDuplicatedReport()) .build(); } diff --git a/src/main/java/friend/spring/service/CommentService.java b/src/main/java/friend/spring/service/CommentService.java index 2d9e309..f0699e9 100644 --- a/src/main/java/friend/spring/service/CommentService.java +++ b/src/main/java/friend/spring/service/CommentService.java @@ -6,6 +6,7 @@ import friend.spring.domain.mapping.Comment_like; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; +import friend.spring.web.dto.PostResponseDTO; import org.springframework.data.domain.Page; import javax.servlet.http.HttpServletRequest; @@ -38,5 +39,5 @@ public interface CommentService { void deleteComment(Long postId, Long commentId, HttpServletRequest request); - Report createReportComment(Long commentId, CommentRequestDTO.CommentReportReq request, HttpServletRequest request2); + PostResponseDTO.ReportResult createReportComment(Long commentId, CommentRequestDTO.CommentReportReq request, HttpServletRequest request2); } diff --git a/src/main/java/friend/spring/service/CommentServiceImpl.java b/src/main/java/friend/spring/service/CommentServiceImpl.java index 5bacee6..7633b87 100644 --- a/src/main/java/friend/spring/service/CommentServiceImpl.java +++ b/src/main/java/friend/spring/service/CommentServiceImpl.java @@ -17,6 +17,7 @@ import friend.spring.security.JwtTokenProvider; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; +import friend.spring.web.dto.PostResponseDTO; import friend.spring.web.dto.SseResponseDTO; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -407,7 +408,7 @@ public void deleteComment(Long postId, Long commentId, HttpServletRequest reques } @Override - public Report createReportComment(Long commentId, CommentRequestDTO.CommentReportReq request, HttpServletRequest request2) { + public PostResponseDTO.ReportResult createReportComment(Long commentId, CommentRequestDTO.CommentReportReq request, HttpServletRequest request2) { Long userId = jwtTokenProvider.getCurrentUser(request2); Optional optionalComment = commentRepository.findById(commentId); @@ -426,12 +427,18 @@ public Report createReportComment(Long commentId, CommentRequestDTO.CommentRepor // 이미 신고된 건인지 확인 Optional optionalReport = reportRepository.findByTargetTypeAndTargetIdAndUserId(ReportType.COMMENT, commentId, userId); if (!optionalReport.isEmpty()) { - throw new CommentHandler(COMMENT_REPORT_DUPLICATE); + return PostResponseDTO.ReportResult.builder() + .report(optionalReport.get()) + .duplicatedReport(true) + .build(); } ReportCategory reportCategory = reportCategoryRepository.findByName(request.getReportCategory()); Report report = CommentConverter.toReportComment(comment, user, reportCategory); - return reportRepository.save(report); + return PostResponseDTO.ReportResult.builder() + .report(reportRepository.save(report)) + .duplicatedReport(false) + .build(); } } diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index e242862..cd4f709 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -3,7 +3,6 @@ import friend.spring.domain.Candidate; import friend.spring.domain.Post; -import friend.spring.domain.Report; import friend.spring.domain.User; import friend.spring.domain.mapping.Post_like; import friend.spring.domain.mapping.Post_scrap; @@ -50,6 +49,6 @@ public interface PostService { void deleteScrapPost(Long postId, HttpServletRequest request); - Report createReportPost(Long postId, PostRequestDTO.PostReportReq request, HttpServletRequest request2); + PostResponseDTO.ReportResult createReportPost(Long postId, PostRequestDTO.PostReportReq request, HttpServletRequest request2); } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 4dd8b2a..7250e12 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -474,7 +474,7 @@ public void deleteScrapPost(Long postId, HttpServletRequest request) { } @Override - public Report createReportPost(Long postId, PostRequestDTO.PostReportReq request, HttpServletRequest request2) { + public PostResponseDTO.ReportResult createReportPost(Long postId, PostRequestDTO.PostReportReq request, HttpServletRequest request2) { Long userId = jwtTokenProvider.getCurrentUser(request2); Optional optionalPost = postRepository.findById(postId); @@ -493,11 +493,17 @@ public Report createReportPost(Long postId, PostRequestDTO.PostReportReq request // 이미 신고된 건인지 확인 Optional optionalReport = reportRepository.findByTargetTypeAndTargetIdAndUserId(ReportType.POST, postId, userId); if (!optionalReport.isEmpty()) { - throw new PostHandler(POST_REPORT_DUPLICATE); + return PostResponseDTO.ReportResult.builder() + .report(optionalReport.get()) + .duplicatedReport(true) + .build(); } ReportCategory reportCategory = reportCategoryRepository.findByName(request.getReportCategory()); Report report = PostConverter.toReportPost(post, user, reportCategory); - return reportRepository.save(report); + return PostResponseDTO.ReportResult.builder() + .report(reportRepository.save(report)) + .duplicatedReport(false) + .build(); } } diff --git a/src/main/java/friend/spring/web/controller/CommentRestController.java b/src/main/java/friend/spring/web/controller/CommentRestController.java index 9c46d91..ea05999 100644 --- a/src/main/java/friend/spring/web/controller/CommentRestController.java +++ b/src/main/java/friend/spring/web/controller/CommentRestController.java @@ -10,6 +10,7 @@ import friend.spring.service.CommentService; import friend.spring.web.dto.CommentRequestDTO; import friend.spring.web.dto.CommentResponseDTO; +import friend.spring.web.dto.PostResponseDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; @@ -219,7 +220,7 @@ public ApiResponse createReportComment( @RequestHeader("atk") String atk, HttpServletRequest request2 ) { - Report commentReport = commentService.createReportComment(commentId, request, request2); + PostResponseDTO.ReportResult commentReport = commentService.createReportComment(commentId, request, request2); return ApiResponse.onSuccess(CommentConverter.toCommentReportRes(commentReport)); } } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 746c972..d018213 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -5,7 +5,6 @@ import friend.spring.converter.PostConverter; import friend.spring.domain.Candidate; import friend.spring.domain.Post; -import friend.spring.domain.Report; import friend.spring.repository.PostRepository; import friend.spring.service.JwtTokenService; import friend.spring.service.PostQueryService; @@ -27,8 +26,6 @@ import javax.validation.Valid; import java.io.IOException; -import static friend.spring.apiPayload.code.status.ErrorStatus.POST_REPORT_DUPLICATE; - @RestController @RequiredArgsConstructor @Validated @@ -326,7 +323,7 @@ public ApiResponse createReportPost( @RequestHeader("atk") String atk, HttpServletRequest request2 ) { - Report postReport = postService.createReportPost(postId, request, request2); + PostResponseDTO.ReportResult postReport = postService.createReportPost(postId, request, request2); return ApiResponse.onSuccess(PostConverter.toPostReportRes(postReport)); } } diff --git a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java index 2726538..b97f840 100644 --- a/src/main/java/friend/spring/web/dto/CommentResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/CommentResponseDTO.java @@ -1,5 +1,6 @@ package friend.spring.web.dto; +import friend.spring.domain.Report; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -77,5 +78,7 @@ public static class myCommentRes { @AllArgsConstructor public static class CommentReportRes { Long reportId; + LocalDateTime createdAt; + Boolean duplicatedReport; } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index acdf06d..c74b4de 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -1,8 +1,8 @@ package friend.spring.web.dto; +import friend.spring.domain.Report; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; -import io.swagger.models.auth.In; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -165,5 +165,16 @@ public static class ScrapCreateRes { @AllArgsConstructor public static class PostReportRes { Long reportId; + LocalDateTime createdAt; + Boolean duplicatedReport; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ReportResult { + Report report; + Boolean duplicatedReport; } } \ No newline at end of file From 618c1adcd69866f54903e4c86c968d37f2ee1230 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Mon, 3 Jun 2024 15:16:11 +0900 Subject: [PATCH 250/255] =?UTF-8?q?#201=20Feat=20:=20RedisRepositoryConfig?= =?UTF-8?q?=20=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=9E=AC=EC=A0=95=EC=9D=98(Ob?= =?UTF-8?q?ject=ED=98=95),=20Redis=EC=97=90=20Queue=EB=A1=9C=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=A0=80=EC=9E=A5,=2010=EA=B0=9C=EA=B9=8C?= =?UTF-8?q?=EC=A7=80=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/config/RedisRepositoryConfig.java | 28 ++++++++++++++++- .../spring/converter/PostConverter.java | 15 ++++++++++ .../friend/spring/domain/Redis/SearchLog.java | 15 ++++++++++ .../spring/service/PostQueryService.java | 7 +++-- .../spring/service/PostQueryServiceImpl.java | 30 ++++++++++++++++++- .../friend/spring/service/PostService.java | 2 +- .../spring/service/PostServiceImpl.java | 4 +-- .../web/controller/PostRestController.java | 19 ++++++++++-- .../spring/web/dto/PostResponseDTO.java | 16 ++++++++++ .../friend/spring/web/dto/UserRequestDTO.java | 8 +++++ 10 files changed, 133 insertions(+), 11 deletions(-) create mode 100644 src/main/java/friend/spring/domain/Redis/SearchLog.java diff --git a/src/main/java/friend/spring/config/RedisRepositoryConfig.java b/src/main/java/friend/spring/config/RedisRepositoryConfig.java index e4380d0..9bb2b6a 100644 --- a/src/main/java/friend/spring/config/RedisRepositoryConfig.java +++ b/src/main/java/friend/spring/config/RedisRepositoryConfig.java @@ -1,5 +1,11 @@ package friend.spring.config; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator; +import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -8,6 +14,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @RequiredArgsConstructor @@ -38,4 +45,23 @@ public RedisTemplate redisTemplate() { redisTemplate.setConnectionFactory(redisConnectionFactory()); return redisTemplate; } -} \ No newline at end of file + + @Bean + public RedisTemplate objectRedisTemplate(RedisConnectionFactory redisConnectionFactory){ + PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator + .builder() + .allowIfSubType(Object.class) + .build(); + ObjectMapper objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.NON_FINAL) + .registerModule(new JavaTimeModule()) + .disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS); + + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(redisConnectionFactory()); + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper)); + return template; + } +} diff --git a/src/main/java/friend/spring/converter/PostConverter.java b/src/main/java/friend/spring/converter/PostConverter.java index 8d4543d..f7f6ca6 100644 --- a/src/main/java/friend/spring/converter/PostConverter.java +++ b/src/main/java/friend/spring/converter/PostConverter.java @@ -1,6 +1,7 @@ package friend.spring.converter; import friend.spring.domain.*; +import friend.spring.domain.Redis.SearchLog; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; @@ -1031,6 +1032,20 @@ public static PostResponseDTO.PostSearchList PostSearchListDTO(Page postLi .isEnd(postList.isLast()) .build(); } + + public static PostResponseDTO.RecentSearchRes toRecentSearchRes(List recentSearchLogs){ + List searchLogList = recentSearchLogs.stream().map(PostConverter::toSearchLog).collect(Collectors.toList()); + return PostResponseDTO.RecentSearchRes.builder() + .recentSearchList(searchLogList) + .build(); + } + + public static PostResponseDTO.SearchLog toSearchLog(SearchLog searchLog){ + return PostResponseDTO.SearchLog.builder() + .name(searchLog.getName()) + .createdAt(searchLog.getCreatedAt()) + .build(); + } } diff --git a/src/main/java/friend/spring/domain/Redis/SearchLog.java b/src/main/java/friend/spring/domain/Redis/SearchLog.java new file mode 100644 index 0000000..ec276ad --- /dev/null +++ b/src/main/java/friend/spring/domain/Redis/SearchLog.java @@ -0,0 +1,15 @@ +package friend.spring.domain.Redis; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Getter +public class SearchLog { + private String name; + private String createdAt; +} diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index 1c5822b..8260614 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -1,11 +1,11 @@ package friend.spring.service; import friend.spring.domain.Post; -import friend.spring.web.dto.PostRequestDTO; -import friend.spring.web.dto.PostResponseDTO; +import friend.spring.domain.Redis.SearchLog; import org.springframework.data.domain.Page; import javax.servlet.http.HttpServletRequest; +import java.util.List; import java.util.Optional; public interface PostQueryService { @@ -22,6 +22,7 @@ public interface PostQueryService { Page getReviewList(Integer page, Integer size, Integer arrange); Page getParentPostList(Integer page, Integer size, HttpServletRequest request); - Page getPostSearch(Integer page, Integer size, String search); + Page getPostSearch(Long userId,Integer page, Integer size, String search); + List getRecentSearchLogs(Long userId); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 69a0115..cd8b90c 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -4,6 +4,7 @@ import friend.spring.apiPayload.code.status.ErrorStatus; import friend.spring.converter.PostConverter; import friend.spring.domain.*; +import friend.spring.domain.Redis.SearchLog; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.PostVoteType; @@ -14,6 +15,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.data.domain.*; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,6 +26,8 @@ import java.util.Optional; import java.util.stream.Collectors; +import static friend.spring.apiPayload.code.status.ErrorStatus.USER_NOT_FOUND; + @Service @RequiredArgsConstructor public class PostQueryServiceImpl implements PostQueryService { @@ -34,6 +38,7 @@ public class PostQueryServiceImpl implements PostQueryService { private final Card_VoteRepository cardVoteRepository; private final CategoryRepository categoryRepository; private final JwtTokenProvider jwtTokenProvider; + private final RedisTemplate objectRedisTemplate; @Override @Transactional @@ -145,8 +150,31 @@ public Page getParentPostList(Integer page, Integer size, HttpServletReque @Override @Transactional - public Page getPostSearch(Integer page, Integer size, String search) { + public Page getPostSearch(Long userId,Integer page, Integer size, String search) { Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); + User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); + String now = LocalDateTime.now().toString(); + String key = "CurrentSearch" + user.getId(); + SearchLog value = SearchLog.builder() + .name(search) + .createdAt(now) + .build(); + Long redisSize = objectRedisTemplate.opsForList().size(key); + if(redisSize == 10){ + objectRedisTemplate.opsForList().rightPop(key); + } + objectRedisTemplate.opsForList().leftPush(key, value); return postRepository.findByKeyWord(search, pageable); } + + public List getRecentSearchLogs(Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); + + String key = "CurrentSearch" + user.getId(); + List objLogs = objectRedisTemplate.opsForList(). + range(key, 0, 10); + List searchLogs = objLogs.stream().map(i -> (SearchLog) i).collect(Collectors.toList()); + return searchLogs; + } } diff --git a/src/main/java/friend/spring/service/PostService.java b/src/main/java/friend/spring/service/PostService.java index 001553f..4e5cc42 100644 --- a/src/main/java/friend/spring/service/PostService.java +++ b/src/main/java/friend/spring/service/PostService.java @@ -9,6 +9,7 @@ import friend.spring.web.dto.CandidateRequestDTO; import friend.spring.web.dto.PostRequestDTO; import friend.spring.web.dto.PostResponseDTO; +import friend.spring.web.dto.UserRequestDTO; import org.springframework.data.domain.Page; import javax.servlet.http.HttpServletRequest; @@ -48,5 +49,4 @@ public interface PostService { Post_scrap createScrapPost(Long postId, HttpServletRequest request); void deleteScrapPost(Long postId, HttpServletRequest request); - } diff --git a/src/main/java/friend/spring/service/PostServiceImpl.java b/src/main/java/friend/spring/service/PostServiceImpl.java index 1937580..86bd18c 100644 --- a/src/main/java/friend/spring/service/PostServiceImpl.java +++ b/src/main/java/friend/spring/service/PostServiceImpl.java @@ -6,6 +6,7 @@ import friend.spring.apiPayload.handler.UserHandler; import friend.spring.converter.PostConverter; import friend.spring.domain.*; +import friend.spring.domain.Redis.SearchLog; import friend.spring.domain.enums.PostState; import friend.spring.domain.enums.PostType; import friend.spring.domain.enums.S3ImageType; @@ -16,6 +17,7 @@ import friend.spring.web.dto.*; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.*; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -456,7 +458,6 @@ public Post_scrap createScrapPost(Long postId, HttpServletRequest request) { @Override public void deleteScrapPost(Long postId, HttpServletRequest request) { Long userId = jwtTokenProvider.getCurrentUser(request); - Optional optionalPost = postRepository.findById(postId); if (optionalPost.isEmpty()) { this.checkPost(false); @@ -475,5 +476,4 @@ public void deleteScrapPost(Long postId, HttpServletRequest request) { Post_scrap post_scrap = optionalPost_scrap.get(); postScrapRepository.delete(post_scrap); } - } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index f93aff4..0174125 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -5,6 +5,7 @@ import friend.spring.converter.PostConverter; import friend.spring.domain.Candidate; import friend.spring.domain.Post; +import friend.spring.domain.Redis.SearchLog; import friend.spring.repository.PostRepository; import friend.spring.service.JwtTokenService; import friend.spring.service.PostQueryService; @@ -25,6 +26,7 @@ import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import java.io.IOException; +import java.util.List; @RestController @RequiredArgsConstructor @@ -310,16 +312,27 @@ public ApiResponse deleteScrapPost( @Parameter(name = "page", description = "query string(RequestParam) - 몇번째 페이지인지 가리키는 page 변수 입니다! (0부터 시작)"), @Parameter(name = "size", description = "query string(RequestParam) - 몇 개씩 불러올지 개수를 세는 변수입니다. (1 이상 자연수로 설정)"), @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), - @Parameter(name = "search", description = "query string(RequestParam) - 검색어.") + @Parameter(name = "keyword", description = "query string(RequestParam) - 검색어.") }) public ApiResponse getPostSearch(@RequestParam(name = "page", defaultValue = "0") Integer page, @RequestParam(name = "size", defaultValue = "15") Integer size, - @RequestParam(name = "search") String search, + @RequestParam(name = "keyword") String keyword, @RequestHeader("atk") String atk, HttpServletRequest request2) { Long userId = jwtTokenService.JwtToId(request2); - Page postPage = postQueryService.getPostSearch(page, size, search); + Page postPage = postQueryService.getPostSearch(userId,page, size, keyword); return ApiResponse.onSuccess(PostConverter.PostSearchListDTO(postPage, userId)); + } + @GetMapping("/post/search/recent-log") + @Operation(summary = "최근 검색어 목록 조회 API", description = "최신순으로 검색어 목록을 최대 10개까지 조회합니다.") + @Parameters({ + @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), + }) + public ApiResponse getRecentSearch(@RequestHeader("atk") String atk, + HttpServletRequest request){ + Long userId = jwtTokenService.JwtToId(request); + List recentSearchLogs = postQueryService.getRecentSearchLogs(userId); + return ApiResponse.onSuccess(PostConverter.toRecentSearchRes(recentSearchLogs)); } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index d5008db..2f42eb5 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -183,4 +183,20 @@ public static class PostSearchRes{ Boolean isLike; Boolean isComment; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class RecentSearchRes { + List recentSearchList; + } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class SearchLog{ + private String name; + private String createdAt; + } } \ No newline at end of file diff --git a/src/main/java/friend/spring/web/dto/UserRequestDTO.java b/src/main/java/friend/spring/web/dto/UserRequestDTO.java index 7bc997e..acd92a4 100644 --- a/src/main/java/friend/spring/web/dto/UserRequestDTO.java +++ b/src/main/java/friend/spring/web/dto/UserRequestDTO.java @@ -142,4 +142,12 @@ public static class PasswordUpdateReq { public static class Delete { private String email; } + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Setter + public static class SearchReq{ + private String name; + private String createdAt; + } } \ No newline at end of file From 9e8633c93e8a9bea24a13aa843a5ca72c0c69953 Mon Sep 17 00:00:00 2001 From: Min Yeong Park Date: Sun, 14 Jul 2024 10:28:23 +0900 Subject: [PATCH 251/255] =?UTF-8?q?#195=20Refactor:=20EB=20environment=20n?= =?UTF-8?q?ame=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev_deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev_deploy.yml b/.github/workflows/dev_deploy.yml index 37c9c9d..94f1e4a 100644 --- a/.github/workflows/dev_deploy.yml +++ b/.github/workflows/dev_deploy.yml @@ -54,7 +54,7 @@ jobs: aws_access_key: ${{ secrets.AWS_ACTION_ACCESS_KEY_ID }} aws_secret_key: ${{ secrets.AWS_ACTION_SECRET_ACCESS_KEY }} application_name: solution-friend-dev - environment_name: Solution-friend-dev-env + environment_name: Solution-friend-dev-env-1 version_label: github-action-${{ steps.current-time.outputs.formattedTime }} region: ap-northeast-2 deployment_package: deploy/deploy.zip From 8fb9ae06a8cd255693b291a27be7c0c708ef9990 Mon Sep 17 00:00:00 2001 From: ls-rain Date: Sun, 8 Sep 2024 13:46:32 +0900 Subject: [PATCH 252/255] =?UTF-8?q?[docs/#206]=20=EC=9D=B4=EC=8A=88,=20PR?= =?UTF-8?q?=20=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\210-\355\205\234\355\224\214\353\246\277.md" | 16 ++++++++++++++++ .github/pull_request_template.md | 13 +++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 ".github/ISSUE_TEMPLATE/\354\235\264\354\212\210-\355\205\234\355\224\214\353\246\277.md" create mode 100644 .github/pull_request_template.md diff --git "a/.github/ISSUE_TEMPLATE/\354\235\264\354\212\210-\355\205\234\355\224\214\353\246\277.md" "b/.github/ISSUE_TEMPLATE/\354\235\264\354\212\210-\355\205\234\355\224\214\353\246\277.md" new file mode 100644 index 0000000..45cf640 --- /dev/null +++ "b/.github/ISSUE_TEMPLATE/\354\235\264\354\212\210-\355\205\234\355\224\214\353\246\277.md" @@ -0,0 +1,16 @@ +--- +name: 이슈 템플릿 +about: 이슈 생성시 해당 템플릿을 사용해주세요 +title: "[Feat/Refactor/Fix/Ci] + 제목" +labels: '' +assignees: '' + +--- + +*** +### 세부내용 + +*** +### 체크 리스트 +- [ ] 구현 +- [ ] 기능 테스트 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..6364938 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ +## 개요 + +## 작업사항 + +## 변경로직 + +### 변경 전 + +### 변경 후 + +## 사용방법 + +## 기타 \ No newline at end of file From 4d7f60d9eabf67eb8211b73b66cf19a3e4259f78 Mon Sep 17 00:00:00 2001 From: kimtaeyoung <62414583+kimtaeyoung201910794@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:22:15 +0900 Subject: [PATCH 253/255] =?UTF-8?q?redis=20sortedset=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 8196 bytes .../spring/converter/PostConverter.java | 8 ++- .../java/friend/spring/domain/Payment.java | 35 ++++++++++ .../spring/domain/enums/PaymentState.java | 5 ++ .../spring/service/PostQueryService.java | 2 +- .../spring/service/PostQueryServiceImpl.java | 65 +++++++++++++----- .../web/controller/PostRestController.java | 16 +++-- 7 files changed, 106 insertions(+), 25 deletions(-) create mode 100644 .DS_Store create mode 100644 src/main/java/friend/spring/domain/Payment.java create mode 100644 src/main/java/friend/spring/domain/enums/PaymentState.java diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b3e225943f03ed9b073b581ee2a0079200c13d0d GIT binary patch literal 8196 zcmeHM&ubGw6#mBkN)W}O&PZj^Uc8tzwJj!YNR#44SP}1f^-mB% z5kc_Og9v)^=FNXW!JBySn;+Som(5D?Ai~bT%nS3rH}9KoH@kTg0BUX6UI7*X)Y!E> zc9_G2rv17X+95Y{mR2zyxQ_ugaSyxLDWJndP#`D}6bK3g1%d+qg93bK>sBjy?^|ye zg91T;N-ChA4-vbzv9qbQ=F!2ylmN8ToHmW0SqGSy$l2K0)LIkDHEs2vT&Qv-hO*)G zM;cBWJDXZ-!=Y?Al*_DKg`!M$#zh7W6TdsDQ5B=dr}9y~Xa=?}@47&!f%x zz0TIk`bN_2*#*?ogGF_dMx)h9T13|#TtB(@^6H1n2aRn1Wn^#LXBsgbpD;_<;)%pS z?BeK`N50SJ`uO<6!CT8Ui|r;kqi;WcU3)X;7kTGz=)7~Iyx7JNEs-7d6Gep2;na(C z#9?e5pGi4N@WFDNa+KgxPYJ{f_1Q7^ zS5t7onP<}L^EmzS{m;*qhZpZ_a`D3I+@}IU`Q# zWx)W?_qmGj`yAfg%`_Rqb*-L4hhLFl9HnsO$eL<>&uZkRt3cC{S4i)O2ILvBvGY+PWZwuC*if+w8h&TxzWe r;b6*fT2qeGW`7v+b3~|)iJeWY postLi .build(); } - public static PostResponseDTO.RecentSearchRes toRecentSearchRes(List recentSearchLogs){ - List searchLogList = recentSearchLogs.stream().map(PostConverter::toSearchLog).collect(Collectors.toList()); + public static PostResponseDTO.RecentSearchRes toRecentSearchRes(List recentSearchLogs) { + List searchLogList = recentSearchLogs.stream() + .map(PostConverter::toSearchLog) // string을 searchLog로 변환gown + .collect(Collectors.toList()); + return PostResponseDTO.RecentSearchRes.builder() .recentSearchList(searchLogList) .build(); } + public static PostResponseDTO.SearchLog toSearchLog(SearchLog searchLog){ return PostResponseDTO.SearchLog.builder() .name(searchLog.getName()) diff --git a/src/main/java/friend/spring/domain/Payment.java b/src/main/java/friend/spring/domain/Payment.java new file mode 100644 index 0000000..2389dbd --- /dev/null +++ b/src/main/java/friend/spring/domain/Payment.java @@ -0,0 +1,35 @@ +//package friend.spring.domain; +// +//import friend.spring.domain.common.BaseEntity; +//import friend.spring.domain.enums.PaymentState; +//import lombok.*; +// +//import javax.persistence.*; +//import java.math.BigDecimal; +// +//@Entity +//@Getter +//@Builder +//@AllArgsConstructor +//@NoArgsConstructor(access = AccessLevel.PROTECTED) +//public class Payment extends BaseEntity { +// +// @Id +// @GeneratedValue(strategy = GenerationType.IDENTITY) +// private Long id; +// +// @Column(nullable = false) +// private BigDecimal amount; +// +// //주문 고유 번호 +// private String merchantUid; +// +// //결제 상태 +// @Enumerated(EnumType.STRING) +// +// private PaymentState paymentState; +// +// +// +// +//} diff --git a/src/main/java/friend/spring/domain/enums/PaymentState.java b/src/main/java/friend/spring/domain/enums/PaymentState.java new file mode 100644 index 0000000..f6be152 --- /dev/null +++ b/src/main/java/friend/spring/domain/enums/PaymentState.java @@ -0,0 +1,5 @@ +//package friend.spring.domain.enums; +// +//public enum PaymentState { +// READY, PAID, FAILED, CANCEL +//} diff --git a/src/main/java/friend/spring/service/PostQueryService.java b/src/main/java/friend/spring/service/PostQueryService.java index 8260614..1283fb6 100644 --- a/src/main/java/friend/spring/service/PostQueryService.java +++ b/src/main/java/friend/spring/service/PostQueryService.java @@ -23,6 +23,6 @@ public interface PostQueryService { Page getParentPostList(Integer page, Integer size, HttpServletRequest request); Page getPostSearch(Long userId,Integer page, Integer size, String search); - List getRecentSearchLogs(Long userId); + List getRecentSearchLogs(Long userId); } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index cd8b90c..f4a0f78 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -2,7 +2,6 @@ import friend.spring.apiPayload.GeneralException; import friend.spring.apiPayload.code.status.ErrorStatus; -import friend.spring.converter.PostConverter; import friend.spring.domain.*; import friend.spring.domain.Redis.SearchLog; import friend.spring.domain.enums.PostState; @@ -10,20 +9,18 @@ import friend.spring.domain.enums.PostVoteType; import friend.spring.repository.*; import friend.spring.security.JwtTokenProvider; -import friend.spring.web.dto.PostRequestDTO; -import friend.spring.web.dto.PostResponseDTO; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.*; -import org.springframework.data.jpa.repository.Query; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ZSetOperations; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import javax.persistence.EntityNotFoundException; import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import static friend.spring.apiPayload.code.status.ErrorStatus.USER_NOT_FOUND; @@ -153,28 +150,60 @@ public Page getParentPostList(Integer page, Integer size, HttpServletReque public Page getPostSearch(Long userId,Integer page, Integer size, String search) { Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); - String now = LocalDateTime.now().toString(); +// String now = LocalDateTime.now().toString(); +// String key = "CurrentSearch" + user.getId(); +// SearchLog value = SearchLog.builder() +// .name(search) +// .createdAt(now) +// .build(); +// Long redisSize = objectRedisTemplate.opsForList().size(key); +// if(redisSize == 10){ +// objectRedisTemplate.opsForList().rightPop(key); +// } +// objectRedisTemplate.opsForList().leftPush(key, value); + + // 기존 큐 방식을 soreted set 방식으로 리팩토링 + + double score = System.currentTimeMillis(); // 시스템의 현재시간을 점수로 사용하였습니다. String key = "CurrentSearch" + user.getId(); - SearchLog value = SearchLog.builder() - .name(search) - .createdAt(now) - .build(); - Long redisSize = objectRedisTemplate.opsForList().size(key); - if(redisSize == 10){ - objectRedisTemplate.opsForList().rightPop(key); + +// SearchLog value = SearchLog.builder() +// .name(search) +// .createdAt(LocalDateTime.now().toString()) +// .build(); + + // 중복된 검색어가 있는 경우 제거 + objectRedisTemplate.opsForZSet().remove(key, search, score); + + objectRedisTemplate.opsForZSet().add(key, search, score); // sorted set에 새로운 검색로그를 저장하였습니다. + + Long redisSize = objectRedisTemplate.opsForZSet().size(key); + + // 10개면 오래된 항목 제거 + if (redisSize != null && redisSize > 10) { + objectRedisTemplate.opsForZSet().removeRange(key, 0, 0); } - objectRedisTemplate.opsForList().leftPush(key, value); + return postRepository.findByKeyWord(search, pageable); } - public List getRecentSearchLogs(Long userId) { + public List getRecentSearchLogs(Long userId) { User user = userRepository.findById(userId) .orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); String key = "CurrentSearch" + user.getId(); - List objLogs = objectRedisTemplate.opsForList(). - range(key, 0, 10); - List searchLogs = objLogs.stream().map(i -> (SearchLog) i).collect(Collectors.toList()); + + // score 높은순으로 10개 가져오기 + Set> recentLogs = objectRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, 9); + + // 검색어 문자열로 변환 + List searchLogs = recentLogs.stream() + .map(ZSetOperations.TypedTuple::getValue) // 문자열 검색어 가져오기 + .map(Object::toString)// string으로 타입을 변환 + .collect(Collectors.toList()); + return searchLogs; } + + } diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index c091e97..2832b22 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -26,7 +26,9 @@ import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import java.io.IOException; +import java.time.LocalDateTime; import java.util.List; +import java.util.stream.Collectors; @RestController @RequiredArgsConstructor @@ -353,11 +355,17 @@ public ApiResponse getPostSearch(@RequestParam(n @Parameters({ @Parameter(name = "atk", description = "RequestHeader - 로그인한 사용자의 accessToken"), }) - public ApiResponse getRecentSearch(@RequestHeader("atk") String atk, - HttpServletRequest request){ + public ApiResponse getRecentSearchLogs(@RequestHeader("atk") String atk, + HttpServletRequest request) { Long userId = jwtTokenService.JwtToId(request); - List recentSearchLogs = postQueryService.getRecentSearchLogs(userId); - return ApiResponse.onSuccess(PostConverter.toRecentSearchRes(recentSearchLogs)); + List recentSearchLogs = postQueryService.getRecentSearchLogs(userId); + // String을 SearchLog로 변환하는 로직 필요 + List searchLogs = recentSearchLogs.stream() + .map(search -> new SearchLog(search, LocalDateTime.now().toString())) + .collect(Collectors.toList()); + + return ApiResponse.onSuccess(PostConverter.toRecentSearchRes(searchLogs)); } + } From 17904f9ed1635dabfaa26d286258eee0dfa41256 Mon Sep 17 00:00:00 2001 From: kimtaeyoung <62414583+kimtaeyoung201910794@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:44:26 +0900 Subject: [PATCH 254/255] =?UTF-8?q?redis=20sortedset=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 8196 -> 8196 bytes .../spring/converter/PostConverter.java | 2 +- .../spring/service/PostQueryServiceImpl.java | 2 +- .../web/controller/PostRestController.java | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.DS_Store b/.DS_Store index b3e225943f03ed9b073b581ee2a0079200c13d0d..f42ce00d3a77392c4c5529183347f00c5b61ac0a 100644 GIT binary patch delta 171 zcmZp1XmQxUDj3JF8O^}Jz`~%%kj{|FP?DSP;*yk;p9B=+Xk2nc`I6f)M^yO~xO}Dd zVGQ|#48!2${M-Vd9tH-X1Cx^lH!>YuFj-8fOHuI_P>2<1Q6@tQLn=cevQ=5SLN_l@ dJ}C5`Y5TFshlCRt7feky% zKki%5 postLi public static PostResponseDTO.RecentSearchRes toRecentSearchRes(List recentSearchLogs) { List searchLogList = recentSearchLogs.stream() - .map(PostConverter::toSearchLog) // string을 searchLog로 변환gown + .map(PostConverter::toSearchLog) // String을 SearchLog로 변환하였습니다. .collect(Collectors.toList()); return PostResponseDTO.RecentSearchRes.builder() diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index f4a0f78..6f4cf15 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -194,7 +194,7 @@ public List getRecentSearchLogs(Long userId) { String key = "CurrentSearch" + user.getId(); // score 높은순으로 10개 가져오기 - Set> recentLogs = objectRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, 9); + Set> recentLogs = objectRedisTemplate.opsForZSet().reverseRangeWithScores(key, 0, 9); // 검색어 문자열로 변환 List searchLogs = recentLogs.stream() diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index 2832b22..a370b2d 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -360,7 +360,7 @@ public ApiResponse getRecentSearchLogs(@Request Long userId = jwtTokenService.JwtToId(request); List recentSearchLogs = postQueryService.getRecentSearchLogs(userId); - // String을 SearchLog로 변환하는 로직 필요 + List searchLogs = recentSearchLogs.stream() .map(search -> new SearchLog(search, LocalDateTime.now().toString())) .collect(Collectors.toList()); From c73571e217c628c7ecf7be3caddfd02c943c9fbf Mon Sep 17 00:00:00 2001 From: kimtaeyoung <62414583+kimtaeyoung201910794@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:56:54 +0900 Subject: [PATCH 255/255] =?UTF-8?q?sortedset=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 8196 -> 8196 bytes .../spring/converter/PostConverter.java | 7 +++---- .../spring/service/PostQueryServiceImpl.java | 19 ------------------ .../web/controller/PostRestController.java | 8 ++++---- .../spring/web/dto/PostResponseDTO.java | 1 - 5 files changed, 7 insertions(+), 28 deletions(-) diff --git a/.DS_Store b/.DS_Store index f42ce00d3a77392c4c5529183347f00c5b61ac0a..b4a0214db6bf936834d81e25c4d8aa05cc6306a5 100644 GIT binary patch delta 173 zcmZp1XmQxUCKy|Ihk=2Cg+Y%YogtH7!&_8A| amhj1kgyWf%A52yjS;%BLb@MS1J8l5cH!*Mk delta 173 zcmZp1XmQxUCK#(3&A`CG!l1{H&XCDalAG`1l9ZF51Qg?FTyjMDlG`yyRQVLRe5Lkb z4Ecf#!{Frn+ybB;1_q%6lamEEG96qnSxl%)QSlZ~h!tp2CPNBCDnlZ&Rav@1H!n{< fDD;n6eEYG postLi .build(); } - public static PostResponseDTO.RecentSearchRes toRecentSearchRes(List recentSearchLogs) { + public static PostResponseDTO.RecentSearchRes toRecentSearchRes(List recentSearchLogs) { List searchLogList = recentSearchLogs.stream() .map(PostConverter::toSearchLog) // String을 SearchLog로 변환하였습니다. .collect(Collectors.toList()); @@ -1060,10 +1060,9 @@ public static PostResponseDTO.RecentSearchRes toRecentSearchRes(List } - public static PostResponseDTO.SearchLog toSearchLog(SearchLog searchLog){ + public static PostResponseDTO.SearchLog toSearchLog(String searchLog){ return PostResponseDTO.SearchLog.builder() - .name(searchLog.getName()) - .createdAt(searchLog.getCreatedAt()) + .name(searchLog) .build(); } } diff --git a/src/main/java/friend/spring/service/PostQueryServiceImpl.java b/src/main/java/friend/spring/service/PostQueryServiceImpl.java index 6f4cf15..1cc9b6d 100644 --- a/src/main/java/friend/spring/service/PostQueryServiceImpl.java +++ b/src/main/java/friend/spring/service/PostQueryServiceImpl.java @@ -150,31 +150,12 @@ public Page getParentPostList(Integer page, Integer size, HttpServletReque public Page getPostSearch(Long userId,Integer page, Integer size, String search) { Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); User user = userRepository.findById(userId).orElseThrow(() -> new GeneralException(USER_NOT_FOUND)); -// String now = LocalDateTime.now().toString(); -// String key = "CurrentSearch" + user.getId(); -// SearchLog value = SearchLog.builder() -// .name(search) -// .createdAt(now) -// .build(); -// Long redisSize = objectRedisTemplate.opsForList().size(key); -// if(redisSize == 10){ -// objectRedisTemplate.opsForList().rightPop(key); -// } -// objectRedisTemplate.opsForList().leftPush(key, value); // 기존 큐 방식을 soreted set 방식으로 리팩토링 double score = System.currentTimeMillis(); // 시스템의 현재시간을 점수로 사용하였습니다. String key = "CurrentSearch" + user.getId(); -// SearchLog value = SearchLog.builder() -// .name(search) -// .createdAt(LocalDateTime.now().toString()) -// .build(); - - // 중복된 검색어가 있는 경우 제거 - objectRedisTemplate.opsForZSet().remove(key, search, score); - objectRedisTemplate.opsForZSet().add(key, search, score); // sorted set에 새로운 검색로그를 저장하였습니다. Long redisSize = objectRedisTemplate.opsForZSet().size(key); diff --git a/src/main/java/friend/spring/web/controller/PostRestController.java b/src/main/java/friend/spring/web/controller/PostRestController.java index a370b2d..2d01c30 100644 --- a/src/main/java/friend/spring/web/controller/PostRestController.java +++ b/src/main/java/friend/spring/web/controller/PostRestController.java @@ -361,11 +361,11 @@ public ApiResponse getRecentSearchLogs(@Request List recentSearchLogs = postQueryService.getRecentSearchLogs(userId); - List searchLogs = recentSearchLogs.stream() - .map(search -> new SearchLog(search, LocalDateTime.now().toString())) - .collect(Collectors.toList()); +// List searchLogs = recentSearchLogs.stream() +// .map(search -> new SearchLog(search, LocalDateTime.now().toString())) +// .collect(Collectors.toList()); - return ApiResponse.onSuccess(PostConverter.toRecentSearchRes(searchLogs)); + return ApiResponse.onSuccess(PostConverter.toRecentSearchRes(recentSearchLogs)); } } diff --git a/src/main/java/friend/spring/web/dto/PostResponseDTO.java b/src/main/java/friend/spring/web/dto/PostResponseDTO.java index ac55e49..6dda30e 100644 --- a/src/main/java/friend/spring/web/dto/PostResponseDTO.java +++ b/src/main/java/friend/spring/web/dto/PostResponseDTO.java @@ -209,7 +209,6 @@ public static class PostReportRes { @AllArgsConstructor public static class SearchLog{ private String name; - private String createdAt; } @Builder