diff --git a/mysql/schema.sql b/mysql/schema.sql index bb422a2e..56acb0f8 100644 --- a/mysql/schema.sql +++ b/mysql/schema.sql @@ -57,3 +57,12 @@ CREATE TABLE likes FOREIGN KEY (user_id) REFERENCES users (id), FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE CASCADE ); + + +CREATE TABLE images +( + id BIGINT AUTO_INCREMENT, + image_url varchar(500) NOT NULL, + filename varchar(255) NOT NULL, + CONSTRAINT images_pk PRIMARY KEY (id) +); diff --git a/src/docs/asciidoc/index.html b/src/docs/asciidoc/index.html index 88a73c93..4f465e00 100644 --- a/src/docs/asciidoc/index.html +++ b/src/docs/asciidoc/index.html @@ -573,9 +573,9 @@

Request

{
-  "email" : "gavin.lakin@hotmail.com",
-  "password" : "BNc@^R!#tM&Prm0WcOIf5Jm1w",
-  "nickname" : "esteban.haag"
+  "email" : "shaniqua.effertz@yahoo.com",
+  "password" : "R87zL7mO&",
+  "nickname" : "nolan.wisozk"
 }
@@ -616,13 +616,13 @@

Request examp
POST /api/v1/auth/signup HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Content-Length: 116
+Content-Length: 103
 Host: docs.api.com
 
 {
-  "email" : "gavin.lakin@hotmail.com",
-  "password" : "BNc@^R!#tM&Prm0WcOIf5Jm1w",
-  "nickname" : "esteban.haag"
+  "email" : "shaniqua.effertz@yahoo.com",
+  "password" : "R87zL7mO&",
+  "nickname" : "nolan.wisozk"
 }
@@ -664,8 +664,8 @@

Request

{
-  "email" : "williams.flatley@yahoo.com",
-  "password" : "Xz#0^3%v8$yk0o%o"
+  "email" : "otto.jacobson@gmail.com",
+  "password" : "D&2t0el8"
 }
@@ -701,12 +701,12 @@

Request e
POST /api/v1/auth/login HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Content-Length: 79
+Content-Length: 68
 Host: docs.api.com
 
 {
-  "email" : "williams.flatley@yahoo.com",
-  "password" : "Xz#0^3%v8$yk0o%o"
+  "email" : "otto.jacobson@gmail.com",
+  "password" : "D&2t0el8"
 }
@@ -717,7 +717,7 @@

Response

{
-  "token" : "a5fbfa1c2fd6a064babe4b7234f141fe57733ee9c53839bb31a0284a7b0a3a49b2894252b81e86078ecc0d9a7e24dc81372376b006d457ede46a8d9d1ea0ff93"
+  "token" : "f8cc772b2b817f5e4ec4b03aaaf6605bcdc99d9d86d494cbbe5c4a18e037c512855b5547445262680dd6173685c2e1eb5daf700e4f0563afb98b32088c980909"
 }
@@ -750,12 +750,12 @@

Respons Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers -Authorization: Bearer a5fbfa1c2fd6a064babe4b7234f141fe57733ee9c53839bb31a0284a7b0a3a49b2894252b81e86078ecc0d9a7e24dc81372376b006d457ede46a8d9d1ea0ff93 +Authorization: Bearer f8cc772b2b817f5e4ec4b03aaaf6605bcdc99d9d86d494cbbe5c4a18e037c512855b5547445262680dd6173685c2e1eb5daf700e4f0563afb98b32088c980909 Content-Type: application/json Content-Length: 146 { - "token" : "a5fbfa1c2fd6a064babe4b7234f141fe57733ee9c53839bb31a0284a7b0a3a49b2894252b81e86078ecc0d9a7e24dc81372376b006d457ede46a8d9d1ea0ff93" + "token" : "f8cc772b2b817f5e4ec4b03aaaf6605bcdc99d9d86d494cbbe5c4a18e037c512855b5547445262680dd6173685c2e1eb5daf700e4f0563afb98b32088c980909" } @@ -802,7 +802,7 @@

Request

Request example

-
PATCH /api/v1/auth/certificate?email=magnolia.becker@yahoo.com HTTP/1.1
+
PATCH /api/v1/auth/certificate?email=kendall.rowe@gmail.com HTTP/1.1
 Content-Type: application/json;charset=UTF-8
 Host: docs.api.com
@@ -868,7 +868,7 @@

Request

Request example

-
PATCH /api/v1/auth/certify?email=emery.kutch@example.com&code=Q8K940 HTTP/1.1
+
PATCH /api/v1/auth/certify?email=catalina.bartell@example.com&code=3ZGzHj HTTP/1.1
 Content-Type: application/json;charset=UTF-8
 Host: docs.api.com
@@ -992,7 +992,7 @@

Request e

@@ -1118,12 +1118,12 @@

Response

"avatarItemId" : 1, "type" : "HAIR", "sex" : "MALE", - "url" : "http://www.williams-crooks.biz/" + "url" : "http://www.gabriel-stanton.biz:13515/laborum?saepe=aliquam&nesciunt=dicta" }, { "avatarItemId" : 2, "type" : "TOP", "sex" : "FEMALE", - "url" : "https://www.elyse-volkman.io/earum/eius?voluptas=rerum&voluptas=exercitationem#vel" + "url" : "https://www.cordelia-bruen.io:52191/" } ]
@@ -1172,18 +1172,18 @@

Respons Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers Content-Type: application/json -Content-Length: 270 +Content-Length: 266 [ { "avatarItemId" : 1, "type" : "HAIR", "sex" : "MALE", - "url" : "http://www.williams-crooks.biz/" + "url" : "http://www.gabriel-stanton.biz:13515/laborum?saepe=aliquam&nesciunt=dicta" }, { "avatarItemId" : 2, "type" : "TOP", "sex" : "FEMALE", - "url" : "https://www.elyse-volkman.io/earum/eius?voluptas=rerum&voluptas=exercitationem#vel" + "url" : "https://www.cordelia-bruen.io:52191/" } ] @@ -1302,7 +1302,7 @@

Request e
POST /api/v1/posts HTTP/1.1
 Content-Type: multipart/form-data;charset=UTF-8; boundary=6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
-Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1NTcwOTg0LCJleHAiOjE3MDU1NzQ1ODQsInVzZXJfaWQiOjF9.mTcgBjKPrrKkjVtfmEk0MJyDI-8PQyKuXrzwr2w1_I8mwQq5lT6PkW9eMPNfCee2vdtxCj6HF_U2rN_yqcbgRA
+Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1Njc0MzY1LCJleHAiOjE3MDU2Nzc5NjUsInVzZXJfaWQiOjF9.7YEbtfN90q-vWJ47IdoUy79KtHJdjSEjVn16sm4glP5UUzuJG705VSJR740ZlBdwKCn5AUDGnOPRpxwSeUC6aA
 Accept: application/json
 Host: docs.api.com
 
@@ -1310,7 +1310,7 @@ 

Request e Content-Disposition: form-data; name=request; filename=request.json Content-Type: application/json -{"title":"Arms and the Man","content":"Tin","coordinate":{"nx":50,"ny":127}} +{"title":"The Grapes of Wrath","content":"Bromine","coordinate":{"nx":50,"ny":127}} --6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm Content-Disposition: form-data; name=postImg; filename=image.jpeg Content-Type: image/jpeg @@ -1327,11 +1327,11 @@

Response

{
   "postId" : 1,
-  "title" : "Arms and the Man",
-  "content" : "Tin",
-  "image" : "https://www.arnulfo-runolfsdottir.info/?architecto=ut&impedit=aperiam",
-  "createdAt" : "2024-01-18T18:43:04.877194",
-  "updatedAt" : "2024-01-18T18:43:04.877208",
+  "title" : "The Grapes of Wrath",
+  "content" : "Bromine",
+  "image" : "https://www.mac-kertzmann.info:56449/voluptas/optio#ipsam",
+  "createdAt" : "2024-01-19T23:26:05.615107",
+  "updatedAt" : "2024-01-19T23:26:05.615121",
   "temperatureArrange" : {
     "min" : 0.0,
     "max" : 15.0
@@ -1405,15 +1405,15 @@ 

Respons Vary: Access-Control-Request-Headers Location: /api/v1/posts/1 Content-Type: application/json -Content-Length: 314 +Content-Length: 309 { "postId" : 1, - "title" : "Arms and the Man", - "content" : "Tin", - "image" : "https://www.arnulfo-runolfsdottir.info/?architecto=ut&impedit=aperiam", - "createdAt" : "2024-01-18T18:43:04.877194", - "updatedAt" : "2024-01-18T18:43:04.877208", + "title" : "The Grapes of Wrath", + "content" : "Bromine", + "image" : "https://www.mac-kertzmann.info:56449/voluptas/optio#ipsam", + "createdAt" : "2024-01-19T23:26:05.615107", + "updatedAt" : "2024-01-19T23:26:05.615121", "temperatureArrange" : { "min" : 0.0, "max" : 15.0 @@ -1489,9 +1489,9 @@

Request H

Request example

-
GET /api/v1/posts/1803095596 HTTP/1.1
+
GET /api/v1/posts/1452329854 HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1NTcwOTg0LCJleHAiOjE3MDU1NzQ1ODQsInVzZXJfaWQiOjF9.mTcgBjKPrrKkjVtfmEk0MJyDI-8PQyKuXrzwr2w1_I8mwQq5lT6PkW9eMPNfCee2vdtxCj6HF_U2rN_yqcbgRA
+Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1Njc0MzY1LCJleHAiOjE3MDU2Nzc5NjUsInVzZXJfaWQiOjF9.7YEbtfN90q-vWJ47IdoUy79KtHJdjSEjVn16sm4glP5UUzuJG705VSJR740ZlBdwKCn5AUDGnOPRpxwSeUC6aA
 Accept: application/json
 Host: docs.api.com
@@ -1503,22 +1503,22 @@

Response

{
-  "postId" : 1803095596,
+  "postId" : 1452329854,
   "writer" : {
-    "userId" : 412308604,
-    "nickname" : "jay.grimes",
-    "image" : "http://www.wyatt-terry.biz/?et=incidunt&possimus=saepe#maxime"
+    "userId" : 301376391,
+    "nickname" : "forrest.windler",
+    "image" : "http://www.kathy-little.io:64848/est/velitsunt"
   },
-  "title" : "The Lathe of Heaven",
-  "content" : "Californium",
-  "image" : "https://www.breanne-waelchi.org:43673/ullam/sequiodio#earum",
-  "createdAt" : "2024-01-18T18:43:04.832065",
-  "updatedAt" : "2024-01-18T18:43:04.832079",
+  "title" : "Arms and the Man",
+  "content" : "Gallium",
+  "image" : "http://www.lesa-becker.info/et?ea=quis&laudantium=voluptas#suscipit",
+  "createdAt" : "2024-01-19T23:26:05.484459",
+  "updatedAt" : "2024-01-19T23:26:05.484469",
   "temperatureArrange" : {
     "min" : 0.0,
     "max" : 15.0
   },
-  "likeCnt" : 33,
+  "likeCnt" : 66,
   "isLike" : 0
 }
@@ -1613,25 +1613,25 @@

Respons Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers Content-Type: application/json -Content-Length: 513 +Content-Length: 504 { - "postId" : 1803095596, + "postId" : 1452329854, "writer" : { - "userId" : 412308604, - "nickname" : "jay.grimes", - "image" : "http://www.wyatt-terry.biz/?et=incidunt&possimus=saepe#maxime" + "userId" : 301376391, + "nickname" : "forrest.windler", + "image" : "http://www.kathy-little.io:64848/est/velitsunt" }, - "title" : "The Lathe of Heaven", - "content" : "Californium", - "image" : "https://www.breanne-waelchi.org:43673/ullam/sequiodio#earum", - "createdAt" : "2024-01-18T18:43:04.832065", - "updatedAt" : "2024-01-18T18:43:04.832079", + "title" : "Arms and the Man", + "content" : "Gallium", + "image" : "http://www.lesa-becker.info/et?ea=quis&laudantium=voluptas#suscipit", + "createdAt" : "2024-01-19T23:26:05.484459", + "updatedAt" : "2024-01-19T23:26:05.484469", "temperatureArrange" : { "min" : 0.0, "max" : 15.0 }, - "likeCnt" : 33, + "likeCnt" : 66, "isLike" : 0 }

@@ -1687,7 +1687,7 @@

Request e
GET /api/v1/posts HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1NTcwOTg0LCJleHAiOjE3MDU1NzQ1ODQsInVzZXJfaWQiOjF9.mTcgBjKPrrKkjVtfmEk0MJyDI-8PQyKuXrzwr2w1_I8mwQq5lT6PkW9eMPNfCee2vdtxCj6HF_U2rN_yqcbgRA
+Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1Njc0MzY1LCJleHAiOjE3MDU2Nzc5NjUsInVzZXJfaWQiOjF9.7YEbtfN90q-vWJ47IdoUy79KtHJdjSEjVn16sm4glP5UUzuJG705VSJR740ZlBdwKCn5AUDGnOPRpxwSeUC6aA
 Accept: application/json
 Host: docs.api.com
@@ -1699,58 +1699,58 @@

Response

[ {
-  "postId" : 1908042653,
+  "postId" : 391756997,
   "writer" : {
-    "userId" : 934467639,
-    "nickname" : "alfredo.schmidt",
-    "image" : "http://www.king-huels.com:45991/nemo/et?quas=vero&debitis=consequatur#ut"
+    "userId" : 563328115,
+    "nickname" : "kraig.waters",
+    "image" : "http://www.ethyl-rau.net/fuga#et"
   },
-  "title" : "An Acceptable Time",
-  "content" : "Cobalt",
-  "image" : "https://www.lowell-rogahn.io:60654/#molestias",
-  "createdAt" : "2024-01-18T18:43:04.779531",
-  "updatedAt" : "2024-01-18T18:43:04.779548",
+  "title" : "The Green Bay Tree",
+  "content" : "Gold",
+  "image" : "https://www.andreas-waelchi.io:32924/",
+  "createdAt" : "2024-01-19T23:26:05.330447",
+  "updatedAt" : "2024-01-19T23:26:05.330461",
   "temperatureArrange" : {
     "min" : 0.0,
     "max" : 15.0
   },
-  "likeCnt" : 54,
+  "likeCnt" : 93,
   "isLike" : 0
 }, {
-  "postId" : 976739760,
+  "postId" : 411854187,
   "writer" : {
-    "userId" : 1468392497,
-    "nickname" : "georgianne.yundt",
-    "image" : "http://www.sherilyn-pollich.org/dolores?cumque=magnam&dolor=nulla#deleniti"
+    "userId" : 845471690,
+    "nickname" : "eugena.spencer",
+    "image" : "https://www.chance-quitzon.io/explicabo/quo?fugiat=nesciunt&sit=necessitatibus#dicta"
   },
-  "title" : "The Little Foxes",
-  "content" : "Helium",
-  "image" : "https://www.georgette-hirthe.net/aperiam/optio?eum=molestiae&aut=officiis#illum",
-  "createdAt" : "2024-01-18T18:43:04.782134",
-  "updatedAt" : "2024-01-18T18:43:04.78215",
+  "title" : "Ah, Wilderness!",
+  "content" : "Cesium",
+  "image" : "https://www.lauralee-lowe.info/odio/non?vel=culpa&autem=sit",
+  "createdAt" : "2024-01-19T23:26:05.334196",
+  "updatedAt" : "2024-01-19T23:26:05.334205",
   "temperatureArrange" : {
     "min" : 0.0,
     "max" : 15.0
   },
-  "likeCnt" : 55,
+  "likeCnt" : 58,
   "isLike" : 0
 }, {
-  "postId" : 1153411505,
+  "postId" : 1984546333,
   "writer" : {
-    "userId" : 682342469,
-    "nickname" : "marlin.nienow",
-    "image" : "https://www.darrick-kozey.io:61868/perspiciatis#quae"
+    "userId" : 1189354801,
+    "nickname" : "khalilah.kunze",
+    "image" : "https://www.rick-marquardt.info:65501/non/voluptatem"
   },
-  "title" : "Precious Bane",
-  "content" : "Potassium",
-  "image" : "http://www.corrine-west.biz/a/dolorem?sit=dolorem&molestias=aliquid",
-  "createdAt" : "2024-01-18T18:43:04.78255",
-  "updatedAt" : "2024-01-18T18:43:04.782565",
+  "title" : "Fair Stood the Wind for France",
+  "content" : "Lutetium",
+  "image" : "https://www.stephane-weber.co:62304/",
+  "createdAt" : "2024-01-19T23:26:05.334755",
+  "updatedAt" : "2024-01-19T23:26:05.334763",
   "temperatureArrange" : {
     "min" : 0.0,
     "max" : 15.0
   },
-  "likeCnt" : 70,
+  "likeCnt" : 45,
   "isLike" : 0
 } ]
@@ -1845,61 +1845,61 @@

Respons Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers Content-Type: application/json -Content-Length: 1566 +Content-Length: 1487 [ { - "postId" : 1908042653, + "postId" : 391756997, "writer" : { - "userId" : 934467639, - "nickname" : "alfredo.schmidt", - "image" : "http://www.king-huels.com:45991/nemo/et?quas=vero&debitis=consequatur#ut" + "userId" : 563328115, + "nickname" : "kraig.waters", + "image" : "http://www.ethyl-rau.net/fuga#et" }, - "title" : "An Acceptable Time", - "content" : "Cobalt", - "image" : "https://www.lowell-rogahn.io:60654/#molestias", - "createdAt" : "2024-01-18T18:43:04.779531", - "updatedAt" : "2024-01-18T18:43:04.779548", + "title" : "The Green Bay Tree", + "content" : "Gold", + "image" : "https://www.andreas-waelchi.io:32924/", + "createdAt" : "2024-01-19T23:26:05.330447", + "updatedAt" : "2024-01-19T23:26:05.330461", "temperatureArrange" : { "min" : 0.0, "max" : 15.0 }, - "likeCnt" : 54, + "likeCnt" : 93, "isLike" : 0 }, { - "postId" : 976739760, + "postId" : 411854187, "writer" : { - "userId" : 1468392497, - "nickname" : "georgianne.yundt", - "image" : "http://www.sherilyn-pollich.org/dolores?cumque=magnam&dolor=nulla#deleniti" + "userId" : 845471690, + "nickname" : "eugena.spencer", + "image" : "https://www.chance-quitzon.io/explicabo/quo?fugiat=nesciunt&sit=necessitatibus#dicta" }, - "title" : "The Little Foxes", - "content" : "Helium", - "image" : "https://www.georgette-hirthe.net/aperiam/optio?eum=molestiae&aut=officiis#illum", - "createdAt" : "2024-01-18T18:43:04.782134", - "updatedAt" : "2024-01-18T18:43:04.78215", + "title" : "Ah, Wilderness!", + "content" : "Cesium", + "image" : "https://www.lauralee-lowe.info/odio/non?vel=culpa&autem=sit", + "createdAt" : "2024-01-19T23:26:05.334196", + "updatedAt" : "2024-01-19T23:26:05.334205", "temperatureArrange" : { "min" : 0.0, "max" : 15.0 }, - "likeCnt" : 55, + "likeCnt" : 58, "isLike" : 0 }, { - "postId" : 1153411505, + "postId" : 1984546333, "writer" : { - "userId" : 682342469, - "nickname" : "marlin.nienow", - "image" : "https://www.darrick-kozey.io:61868/perspiciatis#quae" + "userId" : 1189354801, + "nickname" : "khalilah.kunze", + "image" : "https://www.rick-marquardt.info:65501/non/voluptatem" }, - "title" : "Precious Bane", - "content" : "Potassium", - "image" : "http://www.corrine-west.biz/a/dolorem?sit=dolorem&molestias=aliquid", - "createdAt" : "2024-01-18T18:43:04.78255", - "updatedAt" : "2024-01-18T18:43:04.782565", + "title" : "Fair Stood the Wind for France", + "content" : "Lutetium", + "image" : "https://www.stephane-weber.co:62304/", + "createdAt" : "2024-01-19T23:26:05.334755", + "updatedAt" : "2024-01-19T23:26:05.334763", "temperatureArrange" : { "min" : 0.0, "max" : 15.0 }, - "likeCnt" : 70, + "likeCnt" : 45, "isLike" : 0 } ]

@@ -2003,7 +2003,7 @@

Request
PUT /api/v1/posts/2 HTTP/1.1
 Content-Type: multipart/form-data;charset=UTF-8; boundary=6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
-Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1NTcwOTg0LCJleHAiOjE3MDU1NzQ1ODQsInVzZXJfaWQiOjF9.mTcgBjKPrrKkjVtfmEk0MJyDI-8PQyKuXrzwr2w1_I8mwQq5lT6PkW9eMPNfCee2vdtxCj6HF_U2rN_yqcbgRA
+Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1Njc0MzY1LCJleHAiOjE3MDU2Nzc5NjUsInVzZXJfaWQiOjF9.7YEbtfN90q-vWJ47IdoUy79KtHJdjSEjVn16sm4glP5UUzuJG705VSJR740ZlBdwKCn5AUDGnOPRpxwSeUC6aA
 Accept: application/json
 Host: docs.api.com
 
@@ -2011,7 +2011,7 @@ 

Request Content-Disposition: form-data; name=request; filename=request.json Content-Type: application/json -{"title":"Absalom, Absalom!","content":"Neodymium"} +{"title":"The Little Foxes","content":"Flerovium"} --6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm Content-Disposition: form-data; name=postImg; filename=image.jpeg Content-Type: image/jpeg @@ -2028,11 +2028,11 @@

Response

{
   "postId" : 2,
-  "title" : "Absalom, Absalom!",
-  "content" : "Neodymium",
-  "image" : "https://www.shelby-schaefer.name:21573/et/distinctiofugiat?magnam=consequatur&consectetur=doloremque#corrupti",
-  "createdAt" : "2024-01-18T18:43:04.934907",
-  "updatedAt" : "2024-01-18T18:43:04.934923",
+  "title" : "The Little Foxes",
+  "content" : "Flerovium",
+  "image" : "https://www.whitney-bogisich.org:25925/voluptas/sunt#reiciendis",
+  "createdAt" : "2024-01-19T23:26:05.741933",
+  "updatedAt" : "2024-01-19T23:26:05.741948",
   "temperatureArrange" : {
     "min" : 0.0,
     "max" : 15.0
@@ -2106,15 +2106,15 @@ 

Respo Vary: Access-Control-Request-Headers Location: /api/v1/posts/2 Content-Type: application/json -Content-Length: 361 +Content-Length: 314 { "postId" : 2, - "title" : "Absalom, Absalom!", - "content" : "Neodymium", - "image" : "https://www.shelby-schaefer.name:21573/et/distinctiofugiat?magnam=consequatur&consectetur=doloremque#corrupti", - "createdAt" : "2024-01-18T18:43:04.934907", - "updatedAt" : "2024-01-18T18:43:04.934923", + "title" : "The Little Foxes", + "content" : "Flerovium", + "image" : "https://www.whitney-bogisich.org:25925/voluptas/sunt#reiciendis", + "createdAt" : "2024-01-19T23:26:05.741933", + "updatedAt" : "2024-01-19T23:26:05.741948", "temperatureArrange" : { "min" : 0.0, "max" : 15.0 @@ -2190,8 +2190,8 @@

Request H

Request example

-
DELETE /api/v1/posts/1744803171 HTTP/1.1
-Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1NTcwOTg0LCJleHAiOjE3MDU1NzQ1ODQsInVzZXJfaWQiOjF9.mTcgBjKPrrKkjVtfmEk0MJyDI-8PQyKuXrzwr2w1_I8mwQq5lT6PkW9eMPNfCee2vdtxCj6HF_U2rN_yqcbgRA
+
DELETE /api/v1/posts/367321063 HTTP/1.1
+Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1Njc0MzY1LCJleHAiOjE3MDU2Nzc5NjUsInVzZXJfaWQiOjF9.7YEbtfN90q-vWJ47IdoUy79KtHJdjSEjVn16sm4glP5UUzuJG705VSJR740ZlBdwKCn5AUDGnOPRpxwSeUC6aA
 Host: docs.api.com
@@ -2256,7 +2256,7 @@

Request H
{
-  "postId" : 1251693879
+  "postId" : 134978164
 }
@@ -2286,15 +2286,15 @@

Request H

Request example

-
POST /api/v1/posts/1251693879/likes HTTP/1.1
+
POST /api/v1/posts/134978164/likes HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1NTcwOTgzLCJleHAiOjE3MDU1NzQ1ODMsInVzZXJfaWQiOjIxNDIzNzM3MjN9.soHfQaFbqHJl5xPC3moiDjk4fXWy9l0oTTliB9oSzqsfArjZKeBV5KuWtc_1cm4e1AO-PhBr2V4_m9h2Et_3vg
+Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1Njc0MzYyLCJleHAiOjE3MDU2Nzc5NjIsInVzZXJfaWQiOjExMjQ5OTI2Mn0.PeuawdOnk4BzLdNZY9_Hi_yz_1M6Di1-DM_Y10aBgj_EM0So8KEMOFhF4sjY-Wod8IAAr6K4UCYLo3ZoYlChww
 Accept: application/json
-Content-Length: 27
+Content-Length: 26
 Host: docs.api.com
 
 {
-  "postId" : 1251693879
+  "postId" : 134978164
 }
@@ -2305,9 +2305,9 @@

Response

@@ -2446,7 +2446,7 @@

Request
GET /api/v1/weather?nx=50&ny=127 HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1NTcwOTg3LCJleHAiOjE3MDU1NzQ1ODcsInVzZXJfaWQiOjF9.PXvjVy9boT_qqEC9Vt0SWy2OjUPPj3wbUtTJ5iUyh21-u3C9WfWh_gH2AvAqo3Cj6XWP0twgbUmBUlM_XYChFw
+Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJvb3R3IiwiaWF0IjoxNzA1Njc0MzcyLCJleHAiOjE3MDU2Nzc5NzIsInVzZXJfaWQiOjF9.lvIkeLYQpvhX-M6GBQHaKGBKXKRolg_UMSGNMdfGmGqn2qTSNFVYmETKa6xHMxroNHXtsTy-9DlnRaCALseZ-g
 Accept: application/json
 Host: docs.api.com
@@ -2528,7 +2528,7 @@

Respo diff --git a/src/main/java/com/backendoori/ootw/OotwApplication.java b/src/main/java/com/backendoori/ootw/OotwApplication.java index d1869f36..93d4312b 100644 --- a/src/main/java/com/backendoori/ootw/OotwApplication.java +++ b/src/main/java/com/backendoori/ootw/OotwApplication.java @@ -5,7 +5,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.scheduling.annotation.EnableScheduling; +@EnableScheduling @SpringBootApplication @ConfigurationPropertiesScan public class OotwApplication { diff --git a/src/main/java/com/backendoori/ootw/avatar/controller/AvatarItemController.java b/src/main/java/com/backendoori/ootw/avatar/controller/AvatarItemController.java index 6e0c4c1b..0785a06a 100644 --- a/src/main/java/com/backendoori/ootw/avatar/controller/AvatarItemController.java +++ b/src/main/java/com/backendoori/ootw/avatar/controller/AvatarItemController.java @@ -4,7 +4,7 @@ import com.backendoori.ootw.avatar.dto.AvatarItemRequest; import com.backendoori.ootw.avatar.dto.AvatarItemResponse; import com.backendoori.ootw.avatar.service.AvatarItemService; -import com.backendoori.ootw.common.validation.Image; +import com.backendoori.ootw.image.validation.Image; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; diff --git a/src/main/java/com/backendoori/ootw/avatar/dto/AvatarItemRequest.java b/src/main/java/com/backendoori/ootw/avatar/dto/AvatarItemRequest.java index 6285c895..3ec5e1ea 100644 --- a/src/main/java/com/backendoori/ootw/avatar/dto/AvatarItemRequest.java +++ b/src/main/java/com/backendoori/ootw/avatar/dto/AvatarItemRequest.java @@ -3,7 +3,6 @@ import com.backendoori.ootw.avatar.domain.ItemType; import com.backendoori.ootw.avatar.domain.Sex; import com.backendoori.ootw.common.validation.Enum; -import jakarta.validation.constraints.NotNull; public record AvatarItemRequest( @Enum(enumClass = ItemType.class) diff --git a/src/main/java/com/backendoori/ootw/avatar/service/AvatarItemService.java b/src/main/java/com/backendoori/ootw/avatar/service/AvatarItemService.java index b66b0ff1..94d9bbcb 100644 --- a/src/main/java/com/backendoori/ootw/avatar/service/AvatarItemService.java +++ b/src/main/java/com/backendoori/ootw/avatar/service/AvatarItemService.java @@ -5,9 +5,9 @@ import com.backendoori.ootw.avatar.dto.AvatarItemRequest; import com.backendoori.ootw.avatar.dto.AvatarItemResponse; import com.backendoori.ootw.avatar.repository.AvatarItemRepository; -import com.backendoori.ootw.common.image.ImageFile; -import com.backendoori.ootw.common.image.ImageService; -import com.backendoori.ootw.common.image.exception.SaveException; +import com.backendoori.ootw.image.dto.ImageFile; +import com.backendoori.ootw.image.service.ImageService; +import com.backendoori.ootw.image.exception.SaveException; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/backendoori/ootw/common/image/ImageFile.java b/src/main/java/com/backendoori/ootw/common/image/ImageFile.java deleted file mode 100644 index 1aabf702..00000000 --- a/src/main/java/com/backendoori/ootw/common/image/ImageFile.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.backendoori.ootw.common.image; - -public record ImageFile( - String url, - String fileName -) { - -} diff --git a/src/main/java/com/backendoori/ootw/image/domain/Image.java b/src/main/java/com/backendoori/ootw/image/domain/Image.java new file mode 100644 index 00000000..2470f6cf --- /dev/null +++ b/src/main/java/com/backendoori/ootw/image/domain/Image.java @@ -0,0 +1,33 @@ +package com.backendoori.ootw.image.domain; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Table(name = "images") +@Getter +@Entity +@Builder +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Image { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "image_url", unique = true) + private String ImageUrl; + + @Column(name = "filename") + private String fileName; + +} diff --git a/src/main/java/com/backendoori/ootw/image/dto/ImageFile.java b/src/main/java/com/backendoori/ootw/image/dto/ImageFile.java new file mode 100644 index 00000000..2e2a3cca --- /dev/null +++ b/src/main/java/com/backendoori/ootw/image/dto/ImageFile.java @@ -0,0 +1,12 @@ +package com.backendoori.ootw.image.dto; + +import com.backendoori.ootw.image.domain.Image; + +public record ImageFile( + String url, + String fileName +) { + public static ImageFile from(Image image){ + return new ImageFile(image.getImageUrl(), image.getFileName()); + } +} diff --git a/src/main/java/com/backendoori/ootw/common/image/exception/ImageControllerAdvice.java b/src/main/java/com/backendoori/ootw/image/exception/ImageControllerAdvice.java similarity index 87% rename from src/main/java/com/backendoori/ootw/common/image/exception/ImageControllerAdvice.java rename to src/main/java/com/backendoori/ootw/image/exception/ImageControllerAdvice.java index 91a9b179..ac74aafc 100644 --- a/src/main/java/com/backendoori/ootw/common/image/exception/ImageControllerAdvice.java +++ b/src/main/java/com/backendoori/ootw/image/exception/ImageControllerAdvice.java @@ -1,7 +1,9 @@ -package com.backendoori.ootw.common.image.exception; +package com.backendoori.ootw.image.exception; import com.backendoori.ootw.exception.ErrorResponse; import lombok.extern.slf4j.Slf4j; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -9,6 +11,7 @@ @Slf4j @RestControllerAdvice +@Order(Ordered.HIGHEST_PRECEDENCE) public class ImageControllerAdvice { private static final String IMAGE_RELATED_EXCEPTION = "업로드 요청 중 문제가 발생했습니다."; @@ -30,4 +33,5 @@ public ResponseEntity handleSaveException(SaveException e) { return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY) .body(errorResponse); } + } diff --git a/src/main/java/com/backendoori/ootw/common/image/exception/ImageException.java b/src/main/java/com/backendoori/ootw/image/exception/ImageException.java similarity index 88% rename from src/main/java/com/backendoori/ootw/common/image/exception/ImageException.java rename to src/main/java/com/backendoori/ootw/image/exception/ImageException.java index 2109c917..0f4be035 100644 --- a/src/main/java/com/backendoori/ootw/common/image/exception/ImageException.java +++ b/src/main/java/com/backendoori/ootw/image/exception/ImageException.java @@ -1,4 +1,4 @@ -package com.backendoori.ootw.common.image.exception; +package com.backendoori.ootw.image.exception; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/backendoori/ootw/common/image/exception/SaveException.java b/src/main/java/com/backendoori/ootw/image/exception/SaveException.java similarity index 84% rename from src/main/java/com/backendoori/ootw/common/image/exception/SaveException.java rename to src/main/java/com/backendoori/ootw/image/exception/SaveException.java index 4ec98d5c..a3b647a5 100644 --- a/src/main/java/com/backendoori/ootw/common/image/exception/SaveException.java +++ b/src/main/java/com/backendoori/ootw/image/exception/SaveException.java @@ -1,4 +1,4 @@ -package com.backendoori.ootw.common.image.exception; +package com.backendoori.ootw.image.exception; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/backendoori/ootw/image/repository/ImageRepository.java b/src/main/java/com/backendoori/ootw/image/repository/ImageRepository.java new file mode 100644 index 00000000..2fe3e51f --- /dev/null +++ b/src/main/java/com/backendoori/ootw/image/repository/ImageRepository.java @@ -0,0 +1,8 @@ +package com.backendoori.ootw.image.repository; + +import com.backendoori.ootw.image.domain.Image; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ImageRepository extends JpaRepository { + +} diff --git a/src/main/java/com/backendoori/ootw/common/image/ImageService.java b/src/main/java/com/backendoori/ootw/image/service/ImageService.java similarity index 64% rename from src/main/java/com/backendoori/ootw/common/image/ImageService.java rename to src/main/java/com/backendoori/ootw/image/service/ImageService.java index 1064f453..0a6e5a17 100644 --- a/src/main/java/com/backendoori/ootw/common/image/ImageService.java +++ b/src/main/java/com/backendoori/ootw/image/service/ImageService.java @@ -1,5 +1,6 @@ -package com.backendoori.ootw.common.image; +package com.backendoori.ootw.image.service; +import com.backendoori.ootw.image.dto.ImageFile; import org.springframework.web.multipart.MultipartFile; public interface ImageService { diff --git a/src/main/java/com/backendoori/ootw/image/service/ImageUpdateService.java b/src/main/java/com/backendoori/ootw/image/service/ImageUpdateService.java new file mode 100644 index 00000000..1fe6ab52 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/image/service/ImageUpdateService.java @@ -0,0 +1,55 @@ +package com.backendoori.ootw.image.service; + +import java.util.ArrayList; +import java.util.List; +import com.backendoori.ootw.avatar.domain.AvatarItem; +import com.backendoori.ootw.avatar.repository.AvatarItemRepository; +import com.backendoori.ootw.image.domain.Image; +import com.backendoori.ootw.image.repository.ImageRepository; +import com.backendoori.ootw.post.domain.Post; +import com.backendoori.ootw.post.repository.PostRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ImageUpdateService { + + private final PostRepository postRepository; + private final AvatarItemRepository avatarItemRepository; + private final ImageRepository imageRepository; + private final ImageService imageService; + public static final String TIMEZONE = "Asia/Seoul"; + public static final String CRON = "0 20 00 10 * ?"; + + @Scheduled(cron = CRON, zone = TIMEZONE) // 매월 20일 오전 00시 10분에 실행 + @Async + @Transactional + public void deleteUnused(){ + + List urls = new ArrayList<>(); + + postRepository.findAll() + .stream() + .map(Post::getImageUrl) + .forEach(urls::add); + + avatarItemRepository.findAll() + .stream() + .map(AvatarItem::getImageUrl) + .forEach(urls::add); + + List images = imageRepository.findAll(); + + for(Image image : images){ + if(!urls.contains(image.getImageUrl())){ + imageService.delete(image.getFileName()); + } + } + + } + +} diff --git a/src/main/java/com/backendoori/ootw/common/image/MiniOImageServiceImpl.java b/src/main/java/com/backendoori/ootw/image/service/MiniOImageServiceImpl.java similarity index 52% rename from src/main/java/com/backendoori/ootw/common/image/MiniOImageServiceImpl.java rename to src/main/java/com/backendoori/ootw/image/service/MiniOImageServiceImpl.java index 5dee94e9..959dc883 100644 --- a/src/main/java/com/backendoori/ootw/common/image/MiniOImageServiceImpl.java +++ b/src/main/java/com/backendoori/ootw/image/service/MiniOImageServiceImpl.java @@ -1,21 +1,26 @@ -package com.backendoori.ootw.common.image; +package com.backendoori.ootw.image.service; -import static com.backendoori.ootw.common.image.exception.ImageException.IMAGE_ROLLBACK_FAIL_MESSAGE; -import static com.backendoori.ootw.common.image.exception.ImageException.IMAGE_UPLOAD_FAIL_MESSAGE; -import static com.backendoori.ootw.common.validation.ImageValidator.validateImage; +import static com.backendoori.ootw.image.validation.ImageValidator.validateImage; import java.io.InputStream; -import java.nio.file.Path; +import java.util.UUID; import java.util.concurrent.TimeUnit; -import com.backendoori.ootw.common.image.exception.ImageException; +import com.backendoori.ootw.image.domain.Image; +import com.backendoori.ootw.image.dto.ImageFile; +import com.backendoori.ootw.image.exception.ImageException; import com.backendoori.ootw.config.MiniOConfig; +import com.backendoori.ootw.image.repository.ImageRepository; import io.minio.GetPresignedObjectUrlArgs; import io.minio.MinioClient; import io.minio.PutObjectArgs; import io.minio.RemoveObjectArgs; import io.minio.http.Method; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -29,28 +34,46 @@ public class MiniOImageServiceImpl implements ImageService { private final MinioClient minioClient; private final MiniOConfig miniOConfig; - private Path path; + private final ImageRepository imageRepository; @Override public ImageFile upload(MultipartFile file) { validateImage(file); + String randomFileName = getUniqueFileName(file); try { - path = Path.of(file.getOriginalFilename()); InputStream inputStream = file.getInputStream(); String contentType = file.getContentType(); PutObjectArgs args = PutObjectArgs.builder() .bucket(miniOConfig.getBucket()) - .object(path.toString()) + .object(randomFileName) .stream(inputStream, inputStream.available(), -1) .contentType(contentType) .build(); minioClient.putObject(args); - return new ImageFile(getUrl(), path.toString()); + String url = getUrl(randomFileName); + Image image = saveImage(url, randomFileName); + imageRepository.save(image); + return ImageFile.from(image); } catch (Exception e) { - throw new ImageException(IMAGE_UPLOAD_FAIL_MESSAGE); + throw new ImageException(ImageException.IMAGE_UPLOAD_FAIL_MESSAGE); } } + private static Image saveImage(String url, String randomFileName) { + return Image.builder() + .ImageUrl(url) + .fileName(randomFileName) + .build(); + } + + @NotNull + private static String getUniqueFileName(MultipartFile file) { + String randomUUID = UUID.randomUUID().toString(); + String originalFileName = file.getOriginalFilename(); + + return randomUUID + originalFileName; + } + @Override public void delete(String fileName) { try { @@ -59,21 +82,21 @@ public void delete(String fileName) { .object(fileName) .build()); } catch (Exception e) { - throw new ImageException(IMAGE_ROLLBACK_FAIL_MESSAGE); + throw new ImageException(ImageException.IMAGE_ROLLBACK_FAIL_MESSAGE); } } - private String getUrl() { + private String getUrl(String fileName) { try { return minioClient.getPresignedObjectUrl( GetPresignedObjectUrlArgs.builder() .method(Method.GET) .bucket(miniOConfig.getBucket()) - .object(path.toString()) + .object(fileName) .expiry(DURATION, TimeUnit.HOURS) .build()); } catch (Exception e) { - throw new ImageException(IMAGE_UPLOAD_FAIL_MESSAGE); + throw new ImageException(ImageException.IMAGE_UPLOAD_FAIL_MESSAGE); } } diff --git a/src/main/java/com/backendoori/ootw/image/validation/Enum.java b/src/main/java/com/backendoori/ootw/image/validation/Enum.java new file mode 100644 index 00000000..00cc7084 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/image/validation/Enum.java @@ -0,0 +1,20 @@ +package com.backendoori.ootw.image.validation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +@Target(value = {ElementType.PARAMETER, ElementType.FIELD}) +@Retention(value = RetentionPolicy.RUNTIME) +@Constraint(validatedBy = EnumValidator.class) +public @interface Enum { + + String message() default "유효하지 않은 값입니다 다시 입력해주세요"; + Class[] groups() default {}; + Class[] payload() default {}; + Class> enumClass(); + +} diff --git a/src/main/java/com/backendoori/ootw/image/validation/EnumValidator.java b/src/main/java/com/backendoori/ootw/image/validation/EnumValidator.java new file mode 100644 index 00000000..72a966b4 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/image/validation/EnumValidator.java @@ -0,0 +1,26 @@ +package com.backendoori.ootw.image.validation; + +import java.util.Arrays; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +public class EnumValidator implements ConstraintValidator { + + private Enum annotation; + + @Override + public void initialize(Enum constraintAnnotation) { + this.annotation = constraintAnnotation; + } + + @Override + public boolean isValid(String type, ConstraintValidatorContext context) { + if (type == null) { + return false; + } + + return Arrays.stream(this.annotation.enumClass().getEnumConstants()) + .anyMatch(e -> e.name().equals(type)); + } + +} diff --git a/src/main/java/com/backendoori/ootw/common/validation/Image.java b/src/main/java/com/backendoori/ootw/image/validation/Image.java similarity index 93% rename from src/main/java/com/backendoori/ootw/common/validation/Image.java rename to src/main/java/com/backendoori/ootw/image/validation/Image.java index 23ccc5dc..71719824 100644 --- a/src/main/java/com/backendoori/ootw/common/validation/Image.java +++ b/src/main/java/com/backendoori/ootw/image/validation/Image.java @@ -1,4 +1,4 @@ -package com.backendoori.ootw.common.validation; +package com.backendoori.ootw.image.validation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/src/main/java/com/backendoori/ootw/common/validation/ImageAnnotationValidator.java b/src/main/java/com/backendoori/ootw/image/validation/ImageAnnotationValidator.java similarity index 95% rename from src/main/java/com/backendoori/ootw/common/validation/ImageAnnotationValidator.java rename to src/main/java/com/backendoori/ootw/image/validation/ImageAnnotationValidator.java index e6db8849..db677131 100644 --- a/src/main/java/com/backendoori/ootw/common/validation/ImageAnnotationValidator.java +++ b/src/main/java/com/backendoori/ootw/image/validation/ImageAnnotationValidator.java @@ -1,4 +1,4 @@ -package com.backendoori.ootw.common.validation; +package com.backendoori.ootw.image.validation; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; diff --git a/src/main/java/com/backendoori/ootw/common/validation/ImageValidator.java b/src/main/java/com/backendoori/ootw/image/validation/ImageValidator.java similarity index 95% rename from src/main/java/com/backendoori/ootw/common/validation/ImageValidator.java rename to src/main/java/com/backendoori/ootw/image/validation/ImageValidator.java index d32e4e35..07172a72 100644 --- a/src/main/java/com/backendoori/ootw/common/validation/ImageValidator.java +++ b/src/main/java/com/backendoori/ootw/image/validation/ImageValidator.java @@ -1,4 +1,4 @@ -package com.backendoori.ootw.common.validation; +package com.backendoori.ootw.image.validation; import io.jsonwebtoken.lang.Assert; import lombok.AccessLevel; diff --git a/src/main/java/com/backendoori/ootw/post/controller/PostController.java b/src/main/java/com/backendoori/ootw/post/controller/PostController.java index 91946cb6..4be1c93b 100644 --- a/src/main/java/com/backendoori/ootw/post/controller/PostController.java +++ b/src/main/java/com/backendoori/ootw/post/controller/PostController.java @@ -2,7 +2,7 @@ import java.net.URI; import java.util.List; -import com.backendoori.ootw.common.validation.Image; +import com.backendoori.ootw.image.validation.Image; import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.post.dto.request.PostUpdateRequest; import com.backendoori.ootw.post.dto.response.PostReadResponse; diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index b16e643c..8d641b38 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -7,9 +7,9 @@ import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; -import com.backendoori.ootw.common.image.ImageFile; -import com.backendoori.ootw.common.image.ImageService; -import com.backendoori.ootw.common.image.exception.SaveException; +import com.backendoori.ootw.image.dto.ImageFile; +import com.backendoori.ootw.image.service.ImageService; +import com.backendoori.ootw.image.exception.SaveException; import com.backendoori.ootw.exception.PermissionException; import com.backendoori.ootw.exception.UserNotFoundException; import com.backendoori.ootw.like.domain.Like; diff --git a/src/test/java/com/backendoori/ootw/avatar/controller/AvatarItemControllerTest.java b/src/test/java/com/backendoori/ootw/avatar/controller/AvatarItemControllerTest.java index bc366268..417607da 100644 --- a/src/test/java/com/backendoori/ootw/avatar/controller/AvatarItemControllerTest.java +++ b/src/test/java/com/backendoori/ootw/avatar/controller/AvatarItemControllerTest.java @@ -8,16 +8,19 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.nio.charset.StandardCharsets; +import java.util.stream.Stream; import com.backendoori.ootw.avatar.domain.Sex; import com.backendoori.ootw.avatar.dto.AvatarItemRequest; import com.backendoori.ootw.avatar.repository.AvatarItemRepository; import com.backendoori.ootw.avatar.service.AvatarItemService; -import com.backendoori.ootw.common.image.exception.ImageException; -import com.backendoori.ootw.common.image.exception.SaveException; +import com.backendoori.ootw.image.exception.ImageException; +import com.backendoori.ootw.image.exception.SaveException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.NullAndEmptySource; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; @@ -67,6 +70,27 @@ public void imageUploadTest() throws Exception { .andExpect(status().isCreated()); } + @ParameterizedTest + @MethodSource("provideInvalidAvatarImageInfo") + @DisplayName("아바타 이미지를 등록 시 ItemRequest 가 잘못되면 예외가 발생한다.") + public void imageUploadFailWithInvalidItemRequest(String itemType, String sex) throws Exception { + //given + MockMultipartFile file = new MockMultipartFile("file", "filename.txt", + "image/jpeg", "some xml".getBytes()); + AvatarItemRequest requestDto = new AvatarItemRequest(itemType, sex); + MockMultipartFile request = new MockMultipartFile("request", "filename.txt", + "application/json", objectMapper.writeValueAsBytes(requestDto)); + + //when, then + mockMvc.perform(multipart("/api/v1/avatar-items") + .file(file) + .file(request) + .contentType(MediaType.MULTIPART_FORM_DATA) + .accept(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8)) + .andExpect(status().isBadRequest()); + } + @Test @DisplayName("아바타 등록 요청 중 이미지 등록 중 예외가 발생하면 커스텀 예외가 발생한다.") public void imageUploadException() throws Exception { @@ -185,4 +209,19 @@ public void getItemList() throws Exception { .andExpect(status().isOk()) .andDo(print()); } + + static Stream provideInvalidAvatarImageInfo() { + String validType = "HAIR"; + String validSex = "MALE"; + return java.util.stream.Stream.of( + Arguments.of(null, validSex), + Arguments.of(validType, null), + Arguments.of("", validSex), + Arguments.of(validType, ""), + Arguments.of(" ", validSex), + Arguments.of(validType, " "), + Arguments.of("hair", validSex), + Arguments.of(validType, "female") + ); + } } diff --git a/src/test/java/com/backendoori/ootw/avatar/service/AvatarItemServiceTest.java b/src/test/java/com/backendoori/ootw/avatar/service/AvatarItemServiceTest.java index 9aa81dcc..7e6d60a6 100644 --- a/src/test/java/com/backendoori/ootw/avatar/service/AvatarItemServiceTest.java +++ b/src/test/java/com/backendoori/ootw/avatar/service/AvatarItemServiceTest.java @@ -10,7 +10,7 @@ import com.backendoori.ootw.avatar.dto.AvatarItemRequest; import com.backendoori.ootw.avatar.dto.AvatarItemResponse; import com.backendoori.ootw.avatar.repository.AvatarItemRepository; -import com.backendoori.ootw.common.image.exception.SaveException; +import com.backendoori.ootw.image.exception.SaveException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; diff --git a/src/test/java/com/backendoori/ootw/common/image/MiniOImageServiceImplTest.java b/src/test/java/com/backendoori/ootw/common/image/MiniOImageServiceImplTest.java index b4ba4816..983cdc4d 100644 --- a/src/test/java/com/backendoori/ootw/common/image/MiniOImageServiceImplTest.java +++ b/src/test/java/com/backendoori/ootw/common/image/MiniOImageServiceImplTest.java @@ -7,7 +7,9 @@ import static org.mockito.Mockito.when; import java.util.stream.Stream; -import com.backendoori.ootw.common.image.exception.ImageException; +import com.backendoori.ootw.image.service.ImageService; +import com.backendoori.ootw.image.service.MiniOImageServiceImpl; +import com.backendoori.ootw.image.exception.ImageException; import com.backendoori.ootw.config.MiniOConfig; import io.minio.GetPresignedObjectUrlArgs; import io.minio.MinioClient; diff --git a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java index 59f913a5..765be6e0 100644 --- a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java +++ b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java @@ -20,9 +20,9 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.stream.Stream; -import com.backendoori.ootw.common.image.ImageFile; -import com.backendoori.ootw.common.image.ImageService; -import com.backendoori.ootw.common.image.exception.SaveException; +import com.backendoori.ootw.image.dto.ImageFile; +import com.backendoori.ootw.image.service.ImageService; +import com.backendoori.ootw.image.exception.SaveException; import com.backendoori.ootw.exception.PermissionException; import com.backendoori.ootw.exception.UserNotFoundException; import com.backendoori.ootw.like.repository.LikeRepository;