From 38dddbd4bd87e2874779347219321597a2036cd4 Mon Sep 17 00:00:00 2001 From: messi <“aa01053997956@gmail.com”> Date: Mon, 8 Apr 2024 22:54:02 +0900 Subject: [PATCH 1/6] example 1 completed --- client/package-lock.json | 22 ++++++++++++++++++++++ client/package.json | 1 + client/src/pages/feed.tsx | 31 ++++++++++++++++++++++++++++++- seminar/src/routes/feed.js | 29 +++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/client/package-lock.json b/client/package-lock.json index 4163d30..eddae0c 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -16,6 +16,7 @@ "@types/react": "^18.0.6", "@types/react-dom": "^18.0.2", "axios": "^0.26.1", + "cors": "^2.8.5", "react": "^18.0.0", "react-dom": "^18.0.0", "react-router-dom": "^6.3.0", @@ -5402,6 +5403,18 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cosmiconfig": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", @@ -19826,6 +19839,15 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "cosmiconfig": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", diff --git a/client/package.json b/client/package.json index b09883d..e829220 100644 --- a/client/package.json +++ b/client/package.json @@ -11,6 +11,7 @@ "@types/react": "^18.0.6", "@types/react-dom": "^18.0.2", "axios": "^0.26.1", + "cors": "^2.8.5", "react": "^18.0.0", "react-dom": "^18.0.0", "react-router-dom": "^6.3.0", diff --git a/client/src/pages/feed.tsx b/client/src/pages/feed.tsx index b64c53b..e6b9eca 100644 --- a/client/src/pages/feed.tsx +++ b/client/src/pages/feed.tsx @@ -8,7 +8,7 @@ interface IAPIResponse { id: number, title: string, content: string } const FeedPage = (props: {}) => { const [ LAPIResponse, setLAPIResponse ] = React.useState([]); - const [ NPostCount, setNPostCount ] = React.useState(0); + const [ NPostCount, setNPostCount ] = React.useState(1); const [ SNewPostTitle, setSNewPostTitle ] = React.useState(""); const [ SNewPostContent, setSNewPostContent ] = React.useState(""); @@ -44,6 +44,24 @@ const FeedPage = (props: {}) => { asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); } + const modifyPost = (id: string, altTitle: string, altContent: string) => { + const asyncFun = async() => { + await axios.post( SAPIBase + '/feed/modifyFeed', { id: id, title: altTitle, content: altContent } ); + setLAPIResponse(() => ( + LAPIResponse.map((value) => { + const match = (value.id === parseInt(id)); + if (match) { + return {id: value.id, title: altTitle, content: altContent}; + } + return value; + })) + + ); + + } + asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); + } + return (
@@ -60,6 +78,17 @@ const FeedPage = (props: {}) => {
deletePost(`${val.id}`)}>ⓧ

{ val.title }

{ val.content }

+ +
) }
diff --git a/seminar/src/routes/feed.js b/seminar/src/routes/feed.js index f9c19d9..d8a19cd 100644 --- a/seminar/src/routes/feed.js +++ b/seminar/src/routes/feed.js @@ -36,6 +36,24 @@ class FeedDB { if (BItemDeleted) id--; return BItemDeleted; } + + modifyItem = (item) => { + const { id, title, content } = item; + console.log(id,title,content, typeof id, typeof parseInt(id)); + let BItemModified = false; + + this.#LDataDB = this.#LDataDB.map((value) => { + const match = (value.id === parseInt(id)); + console.log(value.id, id); + if (match) { + console.log("변경") + BItemModified=true; + return {id: value.id, title: title, content: content}; + } + return value; + }); + return BItemModified; + } } const feedDBInst = FeedDB.getInst(); @@ -73,4 +91,15 @@ router.post('/deleteFeed', (req, res) => { } }) +router.post('/modifyFeed', (req, res) => { + try { + const { id, title, content } = req.body; + const modifyResult=feedDBInst.modifyItem({id, title,content}); + if (!modifyResult) return res.status(500).json({ error: "Failed to modify" }) + else return res.status(200).json({ isOK: true }); + } catch (e) { + return res.status(500).json({ error: e }); + } +}) + module.exports = router; \ No newline at end of file From 85a4b25b3feecc333e71403910863e4a64574fd7 Mon Sep 17 00:00:00 2001 From: messi <“aa01053997956@gmail.com”> Date: Mon, 8 Apr 2024 23:22:59 +0900 Subject: [PATCH 2/6] completed example 1 --- seminar/src/routes/feed.js | 1 + 1 file changed, 1 insertion(+) diff --git a/seminar/src/routes/feed.js b/seminar/src/routes/feed.js index d8a19cd..df74cd1 100644 --- a/seminar/src/routes/feed.js +++ b/seminar/src/routes/feed.js @@ -80,6 +80,7 @@ router.post('/addFeed', (req, res) => { } }); + router.post('/deleteFeed', (req, res) => { try { const { id } = req.body; From 8d06ca6f86160c5a261134792df38c32e273b450 Mon Sep 17 00:00:00 2001 From: messi <“aa01053997956@gmail.com”> Date: Tue, 9 Apr 2024 00:53:26 +0900 Subject: [PATCH 3/6] completed example 2:id&pw --- client/src/pages/account.tsx | 12 ++++---- seminar/src/index.js | 2 ++ seminar/src/middleware/auth.js | 12 ++++++++ seminar/src/routes/account.js | 50 ++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 seminar/src/middleware/auth.js create mode 100644 seminar/src/routes/account.js diff --git a/client/src/pages/account.tsx b/client/src/pages/account.tsx index 0fb33ff..f099e30 100644 --- a/client/src/pages/account.tsx +++ b/client/src/pages/account.tsx @@ -5,23 +5,24 @@ import {SAPIBase} from "../tools/api"; import "./css/account.css"; const AccountPage = () => { - const [ SAPIKEY, setSAPIKEY ] = React.useState(""); + const [ ID, setID ] = React.useState(""); + const [ PW, setPW ] = React.useState(""); const [ NBalance, setNBalance ] = React.useState("Not Authorized"); const [ NTransaction, setNTransaction ] = React.useState(0); const getAccountInformation = () => { const asyncFun = async() => { interface IAPIResponse { balance: number }; - const { data } = await axios.post(SAPIBase + '/account/getInfo', { credential: SAPIKEY }); + const { data } = await axios.post(SAPIBase + '/account/getInfo', { id:ID, pw:PW }); setNBalance(data.balance); } - asyncFun().catch((e) => window.alert(`AN ERROR OCCURED: ${e}`)); + asyncFun().catch((e) => alert(`AN ERROR OCCURED: ${e}`)); } const performTransaction = ( amount: number ) => { const asyncFun = async() => { interface IAPIResponse { success: boolean, balance: number, msg: string }; - const { data } = await axios.post(SAPIBase + '/account/transaction', { credential: SAPIKEY, amount: NBalance }); + const { data } = await axios.post(SAPIBase + '/account/transaction', { id:ID, pw:PW, amount: NBalance }); setNTransaction(0); if (!data.success) { window.alert('Transaction Failed:' + data.msg); @@ -39,7 +40,8 @@ const AccountPage = () => {

Account

- Enter API Key: setSAPIKEY(e.target.value)}/> + Enter ID: setID(e.target.value)}/> + Enter PW: setPW(e.target.value)}/>
diff --git a/seminar/src/index.js b/seminar/src/index.js index b668b83..18a9c63 100644 --- a/seminar/src/index.js +++ b/seminar/src/index.js @@ -3,6 +3,7 @@ const cors = require('cors'); const statusRouter = require('./routes/status'); const feedRouter = require('./routes/feed'); +const accountRouter = require('./routes/account'); const app = express(); const port = 8080; @@ -23,6 +24,7 @@ app.use(cors(corsOptions)); app.use('/status', statusRouter); app.use('/feed', feedRouter); +app.use('/account', accountRouter); app.listen(port, () => { console.log(`Example App Listening @ http://localhost:${ port }`); diff --git a/seminar/src/middleware/auth.js b/seminar/src/middleware/auth.js new file mode 100644 index 0000000..45fa4e9 --- /dev/null +++ b/seminar/src/middleware/auth.js @@ -0,0 +1,12 @@ +const authMiddleware = (req, res, next) => { + if (req.body.id === "messi" && req.body.pw === "messI") { + console.log("[AUTH-MIDDLEWARE] Authorized User"); + next(); + } + else { + console.log("[AUTH-MIDDLEWARE] Not Authorized User"); + res.status(401).json({ error: "Not Authorized" }); + } +} + +module.exports = authMiddleware; \ No newline at end of file diff --git a/seminar/src/routes/account.js b/seminar/src/routes/account.js new file mode 100644 index 0000000..51572f8 --- /dev/null +++ b/seminar/src/routes/account.js @@ -0,0 +1,50 @@ +const express = require('express'); +const authMiddleware = require('../middleware/auth'); + +const router = express.Router(); + +class BankDB { + static _inst_; + static getInst = () => { + if ( !BankDB._inst_ ) BankDB._inst_ = new BankDB(); + return BankDB._inst_; + } + + #total = 10000; + + constructor() { console.log("[Bank-DB] DB Init Completed"); } + + getBalance = () => { + return { success: true, data: this.#total }; + } + + transaction = ( amount ) => { + this.#total += amount; + return { success: true, data: this.#total }; + } +} + +const bankDBInst = BankDB.getInst(); + +router.post('/getInfo', authMiddleware, (req, res) => { + try { + const { success, data } = bankDBInst.getBalance(); + if (success) return res.status(200).json({ balance: data }); + else return res.status(500).json({ error: data }); + } catch (e) { + return res.status(500).json({ error: e }); + } +}); + +router.post('/transaction', authMiddleware, (req, res) => { + try { + const { amount } = req.body; + const { success, data } = bankDBInst.transaction( parseInt(amount) ); + if (success) res.status(200).json({ success: true, balance: data, msg: "Transaction success" }); + else res.status(500).json({ error: data }) + } catch (e) { + return res.status(500).json({ error: e }); + } +}) + +module.exports = router; \ No newline at end of file From 2d113f574956fd3e65395fca9f23001829f9783d Mon Sep 17 00:00:00 2001 From: messi <“aa01053997956@gmail.com”> Date: Tue, 9 Apr 2024 01:56:12 +0900 Subject: [PATCH 4/6] =?UTF-8?q?example=202=20id,pw=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pages/account.tsx | 2 +- seminar/src/middleware/auth.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/pages/account.tsx b/client/src/pages/account.tsx index f099e30..a8c79f2 100644 --- a/client/src/pages/account.tsx +++ b/client/src/pages/account.tsx @@ -22,7 +22,7 @@ const AccountPage = () => { const performTransaction = ( amount: number ) => { const asyncFun = async() => { interface IAPIResponse { success: boolean, balance: number, msg: string }; - const { data } = await axios.post(SAPIBase + '/account/transaction', { id:ID, pw:PW, amount: NBalance }); + const { data } = await axios.post(SAPIBase + '/account/transaction', { id:ID, pw:PW, amount: amount }); setNTransaction(0); if (!data.success) { window.alert('Transaction Failed:' + data.msg); diff --git a/seminar/src/middleware/auth.js b/seminar/src/middleware/auth.js index 45fa4e9..744935f 100644 --- a/seminar/src/middleware/auth.js +++ b/seminar/src/middleware/auth.js @@ -1,5 +1,6 @@ const authMiddleware = (req, res, next) => { - if (req.body.id === "messi" && req.body.pw === "messI") { + console.log(process.env) + if (req.body.id === process.env.USER && req.body.pw === process.env.USER) { console.log("[AUTH-MIDDLEWARE] Authorized User"); next(); } From ea6943dc78c5af7a564ddc32143a215f9ed3f3cf Mon Sep 17 00:00:00 2001 From: messi <“aa01053997956@gmail.com”> Date: Tue, 9 Apr 2024 16:03:50 +0900 Subject: [PATCH 5/6] =?UTF-8?q?process.env=20=ED=82=A4=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/src/middleware/auth.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seminar/src/middleware/auth.js b/seminar/src/middleware/auth.js index 744935f..8e0cd7f 100644 --- a/seminar/src/middleware/auth.js +++ b/seminar/src/middleware/auth.js @@ -1,6 +1,6 @@ const authMiddleware = (req, res, next) => { - console.log(process.env) - if (req.body.id === process.env.USER && req.body.pw === process.env.USER) { + key=process.env.API_KEY || process.env.USER; + if (req.body.id === key && req.body.pw === key) { console.log("[AUTH-MIDDLEWARE] Authorized User"); next(); } From e609de8f2ea885ef7d4d600721f6419d647622f3 Mon Sep 17 00:00:00 2001 From: messi <“aa01053997956@gmail.com”> Date: Tue, 9 Apr 2024 16:53:19 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=201?= =?UTF-8?q?:=20=EC=A4=91=EC=9A=94=ED=95=9C=20=ED=8F=AC=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pages/feed.tsx | 32 +++++++++++++++++++++++--------- seminar/src/routes/feed.js | 33 +++++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/client/src/pages/feed.tsx b/client/src/pages/feed.tsx index e6b9eca..1aa1835 100644 --- a/client/src/pages/feed.tsx +++ b/client/src/pages/feed.tsx @@ -4,11 +4,11 @@ import { SAPIBase } from "../tools/api"; import Header from "../components/header"; import "./css/feed.css"; -interface IAPIResponse { id: number, title: string, content: string } +interface IAPIResponse { id: number, title: string, content: string, toggle:boolean } const FeedPage = (props: {}) => { const [ LAPIResponse, setLAPIResponse ] = React.useState([]); - const [ NPostCount, setNPostCount ] = React.useState(1); + const [ NPostCount, setNPostCount ] = React.useState(1); // 처음에 example 들어있음 const [ SNewPostTitle, setSNewPostTitle ] = React.useState(""); const [ SNewPostContent, setSNewPostContent ] = React.useState(""); @@ -17,7 +17,6 @@ const FeedPage = (props: {}) => { const asyncFun = async () => { const { data } = await axios.get( SAPIBase + `/feed/getFeed?count=${ NPostCount }`); console.log(data); - // const data = [ { id: 0, title: "test1", content: "Example body" }, { id: 1, title: "test2", content: "Example body" }, { id: 2, title: "test3", content: "Example body" } ].slice(0, NPostCount); if (BComponentExited) return; setLAPIResponse(data); }; @@ -27,7 +26,7 @@ const FeedPage = (props: {}) => { const createNewPost = () => { const asyncFun = async () => { - await axios.post( SAPIBase + '/feed/addFeed', { title: SNewPostTitle, content: SNewPostContent } ); + await axios.post( SAPIBase + '/feed/addFeed', { title: SNewPostTitle, content: SNewPostContent, toggle:false } ); setNPostCount(NPostCount + 1); setSNewPostTitle(""); setSNewPostContent(""); @@ -46,22 +45,36 @@ const FeedPage = (props: {}) => { const modifyPost = (id: string, altTitle: string, altContent: string) => { const asyncFun = async() => { - await axios.post( SAPIBase + '/feed/modifyFeed', { id: id, title: altTitle, content: altContent } ); + await axios.post( SAPIBase + '/feed/modifyFeed', { id: id, title: altTitle, content: altContent} ); setLAPIResponse(() => ( LAPIResponse.map((value) => { const match = (value.id === parseInt(id)); if (match) { - return {id: value.id, title: altTitle, content: altContent}; + return {id: value.id, title: altTitle, content: altContent, toggle:value.toggle}; } return value; - })) - - ); + }))); } asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); } + const togglePost = (id: string) => { + const asyncFun = async () => { + // One can set X-HTTP-Method header to DELETE to specify deletion as well + await axios.post( SAPIBase + '/feed/toggleFeed', { id: id } ); + setLAPIResponse(() => ( + LAPIResponse.map((value) => { + const match = (value.id === parseInt(id)); + if (match) { + return {id: value.id, title: value.title, content: value.content, toggle:!value.toggle}; + } + return value; + }))); + } + asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); + } + return (
@@ -75,6 +88,7 @@ const FeedPage = (props: {}) => {
{ LAPIResponse.map( (val, i) =>
+

togglePost(`${val.id}`)}>{val.toggle?"★":"☆"}

{/* ?"★":"☆" */}
deletePost(`${val.id}`)}>ⓧ

{ val.title }

{ val.content }

diff --git a/seminar/src/routes/feed.js b/seminar/src/routes/feed.js index df74cd1..88b7805 100644 --- a/seminar/src/routes/feed.js +++ b/seminar/src/routes/feed.js @@ -9,7 +9,7 @@ class FeedDB { return FeedDB._inst_; } - #id = 1; #itemCount = 1; #LDataDB = [{ id: 0, title: "test1", content: "Example body" }]; + #id = 1; #itemCount = 1; #LDataDB = [{ id: 0, title: "test1", content: "Example body", toggle: false }]; constructor() { console.log("[Feed-DB] DB Init Completed"); } @@ -21,7 +21,7 @@ class FeedDB { insertItem = ( item ) => { const { title, content } = item; - this.#LDataDB.push({ id: this.#id, title, content }); + this.#LDataDB.push({ id: this.#id, title, content, toggle:false }); this.#id++; this.#itemCount++; return true; } @@ -39,21 +39,31 @@ class FeedDB { modifyItem = (item) => { const { id, title, content } = item; - console.log(id,title,content, typeof id, typeof parseInt(id)); let BItemModified = false; this.#LDataDB = this.#LDataDB.map((value) => { const match = (value.id === parseInt(id)); - console.log(value.id, id); if (match) { - console.log("변경") BItemModified=true; - return {id: value.id, title: title, content: content}; + return {id: value.id, title, content, toggle: value.toggle}; } return value; }); return BItemModified; } + + toggleItem = (id) => { + let BItemToggled = false; + this.#LDataDB = this.#LDataDB.map((value) => { + const match = (value.id === id); + if (match) { + BItemToggled=true; + return {id: value.id, title: value.title, content:value.content, toggle: !value.toggle}; + } + return value; + }); + return BItemToggled; + } } const feedDBInst = FeedDB.getInst(); @@ -103,4 +113,15 @@ router.post('/modifyFeed', (req, res) => { } }) +router.post('/toggleFeed', (req, res) => { + try{ + const {id} = req.body; + const toggleResult = feedDBInst.toggleItem(parseInt(id)); + if (!toggleResult) return res.status(500).json({ error: "No item deleted" }) + else return res.status(200).json({ isOK: true }); + } catch (e) { + return res.status(500).json({error: e }); + } +}) + module.exports = router; \ No newline at end of file