박유빈

fix the post error and login rendering error

...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
17 ], 17 ],
18 "type": "pwa-node" 18 "type": "pwa-node"
19 }, 19 },
20 - { 20 + {"name": "Launch ",
21 "program": "${workspaceFolder}/app.js", 21 "program": "${workspaceFolder}/app.js",
22 "request": "launch", 22 "request": "launch",
23 "skipFiles": [ 23 "skipFiles": [
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
14 "bcrypt": "^5.0.1", 14 "bcrypt": "^5.0.1",
15 "crypto": "^1.0.1", 15 "crypto": "^1.0.1",
16 "dotenv": "^10.0.0", 16 "dotenv": "^10.0.0",
17 + "ejs": "^3.1.6",
17 "express": "^4.17.1", 18 "express": "^4.17.1",
18 "firebase": "^9.6.0", 19 "firebase": "^9.6.0",
19 "http2": "^3.3.7", 20 "http2": "^3.3.7",
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
25 "koa-passport": "^4.1.4", 26 "koa-passport": "^4.1.4",
26 "koa-router": "^10.1.1", 27 "koa-router": "^10.1.1",
27 "koa-send": "^5.0.1", 28 "koa-send": "^5.0.1",
29 + "koa-views": "^8.0.0",
28 "mongoose": "^6.0.12", 30 "mongoose": "^6.0.12",
29 "nodemailer": "^6.7.1", 31 "nodemailer": "^6.7.1",
30 "passport": "^0.5.0", 32 "passport": "^0.5.0",
...@@ -1145,6 +1147,11 @@ ...@@ -1145,6 +1147,11 @@
1145 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 1147 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
1146 "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 1148 "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
1147 }, 1149 },
1150 + "node_modules/async": {
1151 + "version": "0.9.2",
1152 + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
1153 + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
1154 + },
1148 "node_modules/balanced-match": { 1155 "node_modules/balanced-match": {
1149 "version": "1.0.2", 1156 "version": "1.0.2",
1150 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1157 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
...@@ -1190,6 +1197,11 @@ ...@@ -1190,6 +1197,11 @@
1190 "node": ">= 10.0.0" 1197 "node": ">= 10.0.0"
1191 } 1198 }
1192 }, 1199 },
1200 + "node_modules/bluebird": {
1201 + "version": "3.7.2",
1202 + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
1203 + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
1204 + },
1193 "node_modules/body-parser": { 1205 "node_modules/body-parser": {
1194 "version": "1.19.0", 1206 "version": "1.19.0",
1195 "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 1207 "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
...@@ -1365,16 +1377,54 @@ ...@@ -1365,16 +1377,54 @@
1365 "color-support": "bin.js" 1377 "color-support": "bin.js"
1366 } 1378 }
1367 }, 1379 },
1380 + "node_modules/commander": {
1381 + "version": "2.20.3",
1382 + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
1383 + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
1384 + },
1368 "node_modules/concat-map": { 1385 "node_modules/concat-map": {
1369 "version": "0.0.1", 1386 "version": "0.0.1",
1370 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1387 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1371 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 1388 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
1372 }, 1389 },
1390 + "node_modules/condense-newlines": {
1391 + "version": "0.2.1",
1392 + "resolved": "https://registry.npmjs.org/condense-newlines/-/condense-newlines-0.2.1.tgz",
1393 + "integrity": "sha1-PemFVTE5R10yUCyDsC9gaE0kxV8=",
1394 + "dependencies": {
1395 + "extend-shallow": "^2.0.1",
1396 + "is-whitespace": "^0.3.0",
1397 + "kind-of": "^3.0.2"
1398 + },
1399 + "engines": {
1400 + "node": ">=0.10.0"
1401 + }
1402 + },
1403 + "node_modules/config-chain": {
1404 + "version": "1.1.13",
1405 + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
1406 + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
1407 + "dependencies": {
1408 + "ini": "^1.3.4",
1409 + "proto-list": "~1.2.1"
1410 + }
1411 + },
1373 "node_modules/console-control-strings": { 1412 "node_modules/console-control-strings": {
1374 "version": "1.1.0", 1413 "version": "1.1.0",
1375 "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", 1414 "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
1376 "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" 1415 "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
1377 }, 1416 },
1417 + "node_modules/consolidate": {
1418 + "version": "0.16.0",
1419 + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.16.0.tgz",
1420 + "integrity": "sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==",
1421 + "dependencies": {
1422 + "bluebird": "^3.7.2"
1423 + },
1424 + "engines": {
1425 + "node": ">= 0.10.0"
1426 + }
1427 + },
1378 "node_modules/content-disposition": { 1428 "node_modules/content-disposition": {
1379 "version": "0.5.3", 1429 "version": "0.5.3",
1380 "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 1430 "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
...@@ -1556,16 +1606,57 @@ ...@@ -1556,16 +1606,57 @@
1556 "safe-buffer": "^5.0.1" 1606 "safe-buffer": "^5.0.1"
1557 } 1607 }
1558 }, 1608 },
1609 + "node_modules/editorconfig": {
1610 + "version": "0.15.3",
1611 + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz",
1612 + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==",
1613 + "dependencies": {
1614 + "commander": "^2.19.0",
1615 + "lru-cache": "^4.1.5",
1616 + "semver": "^5.6.0",
1617 + "sigmund": "^1.0.1"
1618 + },
1619 + "bin": {
1620 + "editorconfig": "bin/editorconfig"
1621 + }
1622 + },
1623 + "node_modules/editorconfig/node_modules/lru-cache": {
1624 + "version": "4.1.5",
1625 + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
1626 + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
1627 + "dependencies": {
1628 + "pseudomap": "^1.0.2",
1629 + "yallist": "^2.1.2"
1630 + }
1631 + },
1632 + "node_modules/editorconfig/node_modules/semver": {
1633 + "version": "5.7.1",
1634 + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
1635 + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
1636 + "bin": {
1637 + "semver": "bin/semver"
1638 + }
1639 + },
1640 + "node_modules/editorconfig/node_modules/yallist": {
1641 + "version": "2.1.2",
1642 + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
1643 + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
1644 + },
1559 "node_modules/ee-first": { 1645 "node_modules/ee-first": {
1560 "version": "1.1.1", 1646 "version": "1.1.1",
1561 "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1647 "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
1562 "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 1648 "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
1563 }, 1649 },
1564 "node_modules/ejs": { 1650 "node_modules/ejs": {
1565 - "version": "2.7.4", 1651 + "version": "3.1.6",
1566 - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", 1652 + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
1567 - "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==", 1653 + "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
1568 - "hasInstallScript": true, 1654 + "dependencies": {
1655 + "jake": "^10.6.1"
1656 + },
1657 + "bin": {
1658 + "ejs": "bin/cli.js"
1659 + },
1569 "engines": { 1660 "engines": {
1570 "node": ">=0.10.0" 1661 "node": ">=0.10.0"
1571 } 1662 }
...@@ -1851,6 +1942,17 @@ ...@@ -1851,6 +1942,17 @@
1851 "node": ">= 0.10.0" 1942 "node": ">= 0.10.0"
1852 } 1943 }
1853 }, 1944 },
1945 + "node_modules/extend-shallow": {
1946 + "version": "2.0.1",
1947 + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
1948 + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
1949 + "dependencies": {
1950 + "is-extendable": "^0.1.0"
1951 + },
1952 + "engines": {
1953 + "node": ">=0.10.0"
1954 + }
1955 + },
1854 "node_modules/fast-deep-equal": { 1956 "node_modules/fast-deep-equal": {
1855 "version": "3.1.3", 1957 "version": "3.1.3",
1856 "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1958 "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
...@@ -1892,6 +1994,14 @@ ...@@ -1892,6 +1994,14 @@
1892 "node": "^10.12.0 || >=12.0.0" 1994 "node": "^10.12.0 || >=12.0.0"
1893 } 1995 }
1894 }, 1996 },
1997 + "node_modules/filelist": {
1998 + "version": "1.0.2",
1999 + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
2000 + "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
2001 + "dependencies": {
2002 + "minimatch": "^3.0.4"
2003 + }
2004 + },
1895 "node_modules/finalhandler": { 2005 "node_modules/finalhandler": {
1896 "version": "1.1.2", 2006 "version": "1.1.2",
1897 "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 2007 "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
...@@ -2035,6 +2145,17 @@ ...@@ -2035,6 +2145,17 @@
2035 "node": "6.* || 8.* || >= 10.*" 2145 "node": "6.* || 8.* || >= 10.*"
2036 } 2146 }
2037 }, 2147 },
2148 + "node_modules/get-paths": {
2149 + "version": "0.0.7",
2150 + "resolved": "https://registry.npmjs.org/get-paths/-/get-paths-0.0.7.tgz",
2151 + "integrity": "sha512-0wdJt7C1XKQxuCgouqd+ZvLJ56FQixKoki9MrFaO4EriqzXOiH9gbukaDE1ou08S8Ns3/yDzoBAISNPqj6e6tA==",
2152 + "dependencies": {
2153 + "pify": "^4.0.1"
2154 + },
2155 + "engines": {
2156 + "node": ">=6.4"
2157 + }
2158 + },
2038 "node_modules/glob": { 2159 "node_modules/glob": {
2039 "version": "7.2.0", 2160 "version": "7.2.0",
2040 "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 2161 "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
...@@ -2366,6 +2487,11 @@ ...@@ -2366,6 +2487,11 @@
2366 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 2487 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
2367 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 2488 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
2368 }, 2489 },
2490 + "node_modules/ini": {
2491 + "version": "1.3.8",
2492 + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
2493 + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
2494 + },
2369 "node_modules/ipaddr.js": { 2495 "node_modules/ipaddr.js": {
2370 "version": "1.9.1", 2496 "version": "1.9.1",
2371 "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 2497 "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
...@@ -2374,6 +2500,19 @@ ...@@ -2374,6 +2500,19 @@
2374 "node": ">= 0.10" 2500 "node": ">= 0.10"
2375 } 2501 }
2376 }, 2502 },
2503 + "node_modules/is-buffer": {
2504 + "version": "1.1.6",
2505 + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
2506 + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
2507 + },
2508 + "node_modules/is-extendable": {
2509 + "version": "0.1.1",
2510 + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
2511 + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
2512 + "engines": {
2513 + "node": ">=0.10.0"
2514 + }
2515 + },
2377 "node_modules/is-extglob": { 2516 "node_modules/is-extglob": {
2378 "version": "2.1.1", 2517 "version": "2.1.1",
2379 "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 2518 "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
...@@ -2417,6 +2556,14 @@ ...@@ -2417,6 +2556,14 @@
2417 "node": ">=0.10.0" 2556 "node": ">=0.10.0"
2418 } 2557 }
2419 }, 2558 },
2559 + "node_modules/is-whitespace": {
2560 + "version": "0.3.0",
2561 + "resolved": "https://registry.npmjs.org/is-whitespace/-/is-whitespace-0.3.0.tgz",
2562 + "integrity": "sha1-Fjnssb4DauxppUy7QBz77XEUq38=",
2563 + "engines": {
2564 + "node": ">=0.10.0"
2565 + }
2566 + },
2420 "node_modules/isarray": { 2567 "node_modules/isarray": {
2421 "version": "1.0.0", 2568 "version": "1.0.0",
2422 "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 2569 "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
...@@ -2428,6 +2575,106 @@ ...@@ -2428,6 +2575,106 @@
2428 "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 2575 "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
2429 "dev": true 2576 "dev": true
2430 }, 2577 },
2578 + "node_modules/jake": {
2579 + "version": "10.8.2",
2580 + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
2581 + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
2582 + "dependencies": {
2583 + "async": "0.9.x",
2584 + "chalk": "^2.4.2",
2585 + "filelist": "^1.0.1",
2586 + "minimatch": "^3.0.4"
2587 + },
2588 + "bin": {
2589 + "jake": "bin/cli.js"
2590 + },
2591 + "engines": {
2592 + "node": "*"
2593 + }
2594 + },
2595 + "node_modules/jake/node_modules/ansi-styles": {
2596 + "version": "3.2.1",
2597 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
2598 + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
2599 + "dependencies": {
2600 + "color-convert": "^1.9.0"
2601 + },
2602 + "engines": {
2603 + "node": ">=4"
2604 + }
2605 + },
2606 + "node_modules/jake/node_modules/chalk": {
2607 + "version": "2.4.2",
2608 + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
2609 + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
2610 + "dependencies": {
2611 + "ansi-styles": "^3.2.1",
2612 + "escape-string-regexp": "^1.0.5",
2613 + "supports-color": "^5.3.0"
2614 + },
2615 + "engines": {
2616 + "node": ">=4"
2617 + }
2618 + },
2619 + "node_modules/jake/node_modules/color-convert": {
2620 + "version": "1.9.3",
2621 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
2622 + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
2623 + "dependencies": {
2624 + "color-name": "1.1.3"
2625 + }
2626 + },
2627 + "node_modules/jake/node_modules/color-name": {
2628 + "version": "1.1.3",
2629 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
2630 + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
2631 + },
2632 + "node_modules/jake/node_modules/escape-string-regexp": {
2633 + "version": "1.0.5",
2634 + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
2635 + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
2636 + "engines": {
2637 + "node": ">=0.8.0"
2638 + }
2639 + },
2640 + "node_modules/jake/node_modules/has-flag": {
2641 + "version": "3.0.0",
2642 + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
2643 + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
2644 + "engines": {
2645 + "node": ">=4"
2646 + }
2647 + },
2648 + "node_modules/jake/node_modules/supports-color": {
2649 + "version": "5.5.0",
2650 + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
2651 + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
2652 + "dependencies": {
2653 + "has-flag": "^3.0.0"
2654 + },
2655 + "engines": {
2656 + "node": ">=4"
2657 + }
2658 + },
2659 + "node_modules/js-beautify": {
2660 + "version": "1.14.0",
2661 + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.0.tgz",
2662 + "integrity": "sha512-yuck9KirNSCAwyNJbqW+BxJqJ0NLJ4PwBUzQQACl5O3qHMBXVkXb/rD0ilh/Lat/tn88zSZ+CAHOlk0DsY7GuQ==",
2663 + "dependencies": {
2664 + "config-chain": "^1.1.12",
2665 + "editorconfig": "^0.15.3",
2666 + "glob": "^7.1.3",
2667 + "nopt": "^5.0.0"
2668 + },
2669 + "bin": {
2670 + "css-beautify": "js/bin/css-beautify.js",
2671 + "html-beautify": "js/bin/html-beautify.js",
2672 + "js-beautify": "js/bin/js-beautify.js"
2673 + },
2674 + "engines": {
2675 + "node": ">=10"
2676 + }
2677 + },
2431 "node_modules/js-yaml": { 2678 "node_modules/js-yaml": {
2432 "version": "4.1.0", 2679 "version": "4.1.0",
2433 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 2680 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
...@@ -2554,6 +2801,17 @@ ...@@ -2554,6 +2801,17 @@
2554 "node": ">= 0.6" 2801 "node": ">= 0.6"
2555 } 2802 }
2556 }, 2803 },
2804 + "node_modules/kind-of": {
2805 + "version": "3.2.2",
2806 + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
2807 + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
2808 + "dependencies": {
2809 + "is-buffer": "^1.1.5"
2810 + },
2811 + "engines": {
2812 + "node": ">=0.10.0"
2813 + }
2814 + },
2557 "node_modules/koa": { 2815 "node_modules/koa": {
2558 "version": "2.13.4", 2816 "version": "2.13.4",
2559 "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz", 2817 "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz",
...@@ -2647,6 +2905,15 @@ ...@@ -2647,6 +2905,15 @@
2647 "mz": "^2.6.0" 2905 "mz": "^2.6.0"
2648 } 2906 }
2649 }, 2907 },
2908 + "node_modules/koa-ejs/node_modules/ejs": {
2909 + "version": "2.7.4",
2910 + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
2911 + "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
2912 + "hasInstallScript": true,
2913 + "engines": {
2914 + "node": ">=0.10.0"
2915 + }
2916 + },
2650 "node_modules/koa-passport": { 2917 "node_modules/koa-passport": {
2651 "version": "4.1.4", 2918 "version": "4.1.4",
2652 "resolved": "https://registry.npmjs.org/koa-passport/-/koa-passport-4.1.4.tgz", 2919 "resolved": "https://registry.npmjs.org/koa-passport/-/koa-passport-4.1.4.tgz",
...@@ -2811,6 +3078,49 @@ ...@@ -2811,6 +3078,49 @@
2811 "node": ">=0.6" 3078 "node": ">=0.6"
2812 } 3079 }
2813 }, 3080 },
3081 + "node_modules/koa-views": {
3082 + "version": "8.0.0",
3083 + "resolved": "https://registry.npmjs.org/koa-views/-/koa-views-8.0.0.tgz",
3084 + "integrity": "sha512-nvGKdG8yVyomhouwN060SWd7Q9kGYRr322dwN6jvI04hgiDEW9vsPXEje9OEtBgGXxHURe7xOzo3bxQ3DBc1Nw==",
3085 + "dependencies": {
3086 + "consolidate": "^0.16.0",
3087 + "debug": "^4.1.0",
3088 + "get-paths": "0.0.7",
3089 + "koa-send": "^5.0.0",
3090 + "mz": "^2.4.0",
3091 + "pretty": "^2.0.0",
3092 + "resolve-path": "^1.4.0"
3093 + },
3094 + "peerDependencies": {
3095 + "@types/koa": "^2.13.1"
3096 + },
3097 + "peerDependenciesMeta": {
3098 + "@types/koa": {
3099 + "optional": true
3100 + }
3101 + }
3102 + },
3103 + "node_modules/koa-views/node_modules/debug": {
3104 + "version": "4.3.3",
3105 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
3106 + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
3107 + "dependencies": {
3108 + "ms": "2.1.2"
3109 + },
3110 + "engines": {
3111 + "node": ">=6.0"
3112 + },
3113 + "peerDependenciesMeta": {
3114 + "supports-color": {
3115 + "optional": true
3116 + }
3117 + }
3118 + },
3119 + "node_modules/koa-views/node_modules/ms": {
3120 + "version": "2.1.2",
3121 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
3122 + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
3123 + },
2814 "node_modules/koa/node_modules/debug": { 3124 "node_modules/koa/node_modules/debug": {
2815 "version": "4.3.2", 3125 "version": "4.3.2",
2816 "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", 3126 "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
...@@ -3460,6 +3770,14 @@ ...@@ -3460,6 +3770,14 @@
3460 "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 3770 "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
3461 "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 3771 "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
3462 }, 3772 },
3773 + "node_modules/pify": {
3774 + "version": "4.0.1",
3775 + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
3776 + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
3777 + "engines": {
3778 + "node": ">=6"
3779 + }
3780 + },
3463 "node_modules/prelude-ls": { 3781 "node_modules/prelude-ls": {
3464 "version": "1.2.1", 3782 "version": "1.2.1",
3465 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 3783 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
...@@ -3469,6 +3787,19 @@ ...@@ -3469,6 +3787,19 @@
3469 "node": ">= 0.8.0" 3787 "node": ">= 0.8.0"
3470 } 3788 }
3471 }, 3789 },
3790 + "node_modules/pretty": {
3791 + "version": "2.0.0",
3792 + "resolved": "https://registry.npmjs.org/pretty/-/pretty-2.0.0.tgz",
3793 + "integrity": "sha1-rbx5YLe7/iiaVX3F9zdhmiINBqU=",
3794 + "dependencies": {
3795 + "condense-newlines": "^0.2.1",
3796 + "extend-shallow": "^2.0.1",
3797 + "js-beautify": "^1.6.12"
3798 + },
3799 + "engines": {
3800 + "node": ">=0.10.0"
3801 + }
3802 + },
3472 "node_modules/process-nextick-args": { 3803 "node_modules/process-nextick-args": {
3473 "version": "2.0.1", 3804 "version": "2.0.1",
3474 "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 3805 "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
...@@ -3488,6 +3819,11 @@ ...@@ -3488,6 +3819,11 @@
3488 "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", 3819 "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz",
3489 "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==" 3820 "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g=="
3490 }, 3821 },
3822 + "node_modules/proto-list": {
3823 + "version": "1.2.4",
3824 + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
3825 + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk="
3826 + },
3491 "node_modules/protobufjs": { 3827 "node_modules/protobufjs": {
3492 "version": "6.11.2", 3828 "version": "6.11.2",
3493 "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", 3829 "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz",
...@@ -3525,6 +3861,11 @@ ...@@ -3525,6 +3861,11 @@
3525 "node": ">= 0.10" 3861 "node": ">= 0.10"
3526 } 3862 }
3527 }, 3863 },
3864 + "node_modules/pseudomap": {
3865 + "version": "1.0.2",
3866 + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
3867 + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
3868 + },
3528 "node_modules/punycode": { 3869 "node_modules/punycode": {
3529 "version": "2.1.1", 3870 "version": "2.1.1",
3530 "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 3871 "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
...@@ -3796,6 +4137,11 @@ ...@@ -3796,6 +4137,11 @@
3796 "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", 4137 "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz",
3797 "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" 4138 "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA=="
3798 }, 4139 },
4140 + "node_modules/sigmund": {
4141 + "version": "1.0.1",
4142 + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
4143 + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA="
4144 + },
3799 "node_modules/signal-exit": { 4145 "node_modules/signal-exit": {
3800 "version": "3.0.6", 4146 "version": "3.0.6",
3801 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", 4147 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
...@@ -5253,6 +5599,11 @@ ...@@ -5253,6 +5599,11 @@
5253 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 5599 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
5254 "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 5600 "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
5255 }, 5601 },
5602 + "async": {
5603 + "version": "0.9.2",
5604 + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
5605 + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
5606 + },
5256 "balanced-match": { 5607 "balanced-match": {
5257 "version": "1.0.2", 5608 "version": "1.0.2",
5258 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 5609 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
...@@ -5277,6 +5628,11 @@ ...@@ -5277,6 +5628,11 @@
5277 "node-addon-api": "^3.1.0" 5628 "node-addon-api": "^3.1.0"
5278 } 5629 }
5279 }, 5630 },
5631 + "bluebird": {
5632 + "version": "3.7.2",
5633 + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
5634 + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
5635 + },
5280 "body-parser": { 5636 "body-parser": {
5281 "version": "1.19.0", 5637 "version": "1.19.0",
5282 "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 5638 "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
...@@ -5404,16 +5760,48 @@ ...@@ -5404,16 +5760,48 @@
5404 "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", 5760 "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
5405 "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" 5761 "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="
5406 }, 5762 },
5763 + "commander": {
5764 + "version": "2.20.3",
5765 + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
5766 + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
5767 + },
5407 "concat-map": { 5768 "concat-map": {
5408 "version": "0.0.1", 5769 "version": "0.0.1",
5409 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 5770 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
5410 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 5771 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
5411 }, 5772 },
5773 + "condense-newlines": {
5774 + "version": "0.2.1",
5775 + "resolved": "https://registry.npmjs.org/condense-newlines/-/condense-newlines-0.2.1.tgz",
5776 + "integrity": "sha1-PemFVTE5R10yUCyDsC9gaE0kxV8=",
5777 + "requires": {
5778 + "extend-shallow": "^2.0.1",
5779 + "is-whitespace": "^0.3.0",
5780 + "kind-of": "^3.0.2"
5781 + }
5782 + },
5783 + "config-chain": {
5784 + "version": "1.1.13",
5785 + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
5786 + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
5787 + "requires": {
5788 + "ini": "^1.3.4",
5789 + "proto-list": "~1.2.1"
5790 + }
5791 + },
5412 "console-control-strings": { 5792 "console-control-strings": {
5413 "version": "1.1.0", 5793 "version": "1.1.0",
5414 "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", 5794 "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
5415 "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" 5795 "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
5416 }, 5796 },
5797 + "consolidate": {
5798 + "version": "0.16.0",
5799 + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.16.0.tgz",
5800 + "integrity": "sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==",
5801 + "requires": {
5802 + "bluebird": "^3.7.2"
5803 + }
5804 + },
5417 "content-disposition": { 5805 "content-disposition": {
5418 "version": "0.5.3", 5806 "version": "0.5.3",
5419 "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 5807 "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
...@@ -5555,15 +5943,50 @@ ...@@ -5555,15 +5943,50 @@
5555 "safe-buffer": "^5.0.1" 5943 "safe-buffer": "^5.0.1"
5556 } 5944 }
5557 }, 5945 },
5946 + "editorconfig": {
5947 + "version": "0.15.3",
5948 + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz",
5949 + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==",
5950 + "requires": {
5951 + "commander": "^2.19.0",
5952 + "lru-cache": "^4.1.5",
5953 + "semver": "^5.6.0",
5954 + "sigmund": "^1.0.1"
5955 + },
5956 + "dependencies": {
5957 + "lru-cache": {
5958 + "version": "4.1.5",
5959 + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
5960 + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
5961 + "requires": {
5962 + "pseudomap": "^1.0.2",
5963 + "yallist": "^2.1.2"
5964 + }
5965 + },
5966 + "semver": {
5967 + "version": "5.7.1",
5968 + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
5969 + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
5970 + },
5971 + "yallist": {
5972 + "version": "2.1.2",
5973 + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
5974 + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
5975 + }
5976 + }
5977 + },
5558 "ee-first": { 5978 "ee-first": {
5559 "version": "1.1.1", 5979 "version": "1.1.1",
5560 "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 5980 "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
5561 "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 5981 "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
5562 }, 5982 },
5563 "ejs": { 5983 "ejs": {
5564 - "version": "2.7.4", 5984 + "version": "3.1.6",
5565 - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", 5985 + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
5566 - "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" 5986 + "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
5987 + "requires": {
5988 + "jake": "^10.6.1"
5989 + }
5567 }, 5990 },
5568 "emoji-regex": { 5991 "emoji-regex": {
5569 "version": "8.0.0", 5992 "version": "8.0.0",
...@@ -5779,6 +6202,14 @@ ...@@ -5779,6 +6202,14 @@
5779 "vary": "~1.1.2" 6202 "vary": "~1.1.2"
5780 } 6203 }
5781 }, 6204 },
6205 + "extend-shallow": {
6206 + "version": "2.0.1",
6207 + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
6208 + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
6209 + "requires": {
6210 + "is-extendable": "^0.1.0"
6211 + }
6212 + },
5782 "fast-deep-equal": { 6213 "fast-deep-equal": {
5783 "version": "3.1.3", 6214 "version": "3.1.3",
5784 "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 6215 "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
...@@ -5814,6 +6245,14 @@ ...@@ -5814,6 +6245,14 @@
5814 "flat-cache": "^3.0.4" 6245 "flat-cache": "^3.0.4"
5815 } 6246 }
5816 }, 6247 },
6248 + "filelist": {
6249 + "version": "1.0.2",
6250 + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
6251 + "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
6252 + "requires": {
6253 + "minimatch": "^3.0.4"
6254 + }
6255 + },
5817 "finalhandler": { 6256 "finalhandler": {
5818 "version": "1.1.2", 6257 "version": "1.1.2",
5819 "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 6258 "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
...@@ -5932,6 +6371,14 @@ ...@@ -5932,6 +6371,14 @@
5932 "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 6371 "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
5933 "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 6372 "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
5934 }, 6373 },
6374 + "get-paths": {
6375 + "version": "0.0.7",
6376 + "resolved": "https://registry.npmjs.org/get-paths/-/get-paths-0.0.7.tgz",
6377 + "integrity": "sha512-0wdJt7C1XKQxuCgouqd+ZvLJ56FQixKoki9MrFaO4EriqzXOiH9gbukaDE1ou08S8Ns3/yDzoBAISNPqj6e6tA==",
6378 + "requires": {
6379 + "pify": "^4.0.1"
6380 + }
6381 + },
5935 "glob": { 6382 "glob": {
5936 "version": "7.2.0", 6383 "version": "7.2.0",
5937 "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 6384 "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
...@@ -6180,11 +6627,26 @@ ...@@ -6180,11 +6627,26 @@
6180 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 6627 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
6181 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 6628 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
6182 }, 6629 },
6630 + "ini": {
6631 + "version": "1.3.8",
6632 + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
6633 + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
6634 + },
6183 "ipaddr.js": { 6635 "ipaddr.js": {
6184 "version": "1.9.1", 6636 "version": "1.9.1",
6185 "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 6637 "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
6186 "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 6638 "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
6187 }, 6639 },
6640 + "is-buffer": {
6641 + "version": "1.1.6",
6642 + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
6643 + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
6644 + },
6645 + "is-extendable": {
6646 + "version": "0.1.1",
6647 + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
6648 + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
6649 + },
6188 "is-extglob": { 6650 "is-extglob": {
6189 "version": "2.1.1", 6651 "version": "2.1.1",
6190 "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 6652 "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
...@@ -6213,6 +6675,11 @@ ...@@ -6213,6 +6675,11 @@
6213 "is-extglob": "^2.1.1" 6675 "is-extglob": "^2.1.1"
6214 } 6676 }
6215 }, 6677 },
6678 + "is-whitespace": {
6679 + "version": "0.3.0",
6680 + "resolved": "https://registry.npmjs.org/is-whitespace/-/is-whitespace-0.3.0.tgz",
6681 + "integrity": "sha1-Fjnssb4DauxppUy7QBz77XEUq38="
6682 + },
6216 "isarray": { 6683 "isarray": {
6217 "version": "1.0.0", 6684 "version": "1.0.0",
6218 "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 6685 "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
...@@ -6224,6 +6691,79 @@ ...@@ -6224,6 +6691,79 @@
6224 "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 6691 "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
6225 "dev": true 6692 "dev": true
6226 }, 6693 },
6694 + "jake": {
6695 + "version": "10.8.2",
6696 + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
6697 + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
6698 + "requires": {
6699 + "async": "0.9.x",
6700 + "chalk": "^2.4.2",
6701 + "filelist": "^1.0.1",
6702 + "minimatch": "^3.0.4"
6703 + },
6704 + "dependencies": {
6705 + "ansi-styles": {
6706 + "version": "3.2.1",
6707 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
6708 + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
6709 + "requires": {
6710 + "color-convert": "^1.9.0"
6711 + }
6712 + },
6713 + "chalk": {
6714 + "version": "2.4.2",
6715 + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
6716 + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
6717 + "requires": {
6718 + "ansi-styles": "^3.2.1",
6719 + "escape-string-regexp": "^1.0.5",
6720 + "supports-color": "^5.3.0"
6721 + }
6722 + },
6723 + "color-convert": {
6724 + "version": "1.9.3",
6725 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
6726 + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
6727 + "requires": {
6728 + "color-name": "1.1.3"
6729 + }
6730 + },
6731 + "color-name": {
6732 + "version": "1.1.3",
6733 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
6734 + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
6735 + },
6736 + "escape-string-regexp": {
6737 + "version": "1.0.5",
6738 + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
6739 + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
6740 + },
6741 + "has-flag": {
6742 + "version": "3.0.0",
6743 + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
6744 + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
6745 + },
6746 + "supports-color": {
6747 + "version": "5.5.0",
6748 + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
6749 + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
6750 + "requires": {
6751 + "has-flag": "^3.0.0"
6752 + }
6753 + }
6754 + }
6755 + },
6756 + "js-beautify": {
6757 + "version": "1.14.0",
6758 + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.0.tgz",
6759 + "integrity": "sha512-yuck9KirNSCAwyNJbqW+BxJqJ0NLJ4PwBUzQQACl5O3qHMBXVkXb/rD0ilh/Lat/tn88zSZ+CAHOlk0DsY7GuQ==",
6760 + "requires": {
6761 + "config-chain": "^1.1.12",
6762 + "editorconfig": "^0.15.3",
6763 + "glob": "^7.1.3",
6764 + "nopt": "^5.0.0"
6765 + }
6766 + },
6227 "js-yaml": { 6767 "js-yaml": {
6228 "version": "4.1.0", 6768 "version": "4.1.0",
6229 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 6769 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
...@@ -6341,6 +6881,14 @@ ...@@ -6341,6 +6881,14 @@
6341 "tsscmp": "1.0.6" 6881 "tsscmp": "1.0.6"
6342 } 6882 }
6343 }, 6883 },
6884 + "kind-of": {
6885 + "version": "3.2.2",
6886 + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
6887 + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
6888 + "requires": {
6889 + "is-buffer": "^1.1.5"
6890 + }
6891 + },
6344 "koa": { 6892 "koa": {
6345 "version": "2.13.4", 6893 "version": "2.13.4",
6346 "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz", 6894 "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz",
...@@ -6445,6 +6993,13 @@ ...@@ -6445,6 +6993,13 @@
6445 "debug": "^2.6.1", 6993 "debug": "^2.6.1",
6446 "ejs": "^2.6.1", 6994 "ejs": "^2.6.1",
6447 "mz": "^2.6.0" 6995 "mz": "^2.6.0"
6996 + },
6997 + "dependencies": {
6998 + "ejs": {
6999 + "version": "2.7.4",
7000 + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
7001 + "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA=="
7002 + }
6448 } 7003 }
6449 }, 7004 },
6450 "koa-passport": { 7005 "koa-passport": {
...@@ -6577,6 +7132,35 @@ ...@@ -6577,6 +7132,35 @@
6577 } 7132 }
6578 } 7133 }
6579 }, 7134 },
7135 + "koa-views": {
7136 + "version": "8.0.0",
7137 + "resolved": "https://registry.npmjs.org/koa-views/-/koa-views-8.0.0.tgz",
7138 + "integrity": "sha512-nvGKdG8yVyomhouwN060SWd7Q9kGYRr322dwN6jvI04hgiDEW9vsPXEje9OEtBgGXxHURe7xOzo3bxQ3DBc1Nw==",
7139 + "requires": {
7140 + "consolidate": "^0.16.0",
7141 + "debug": "^4.1.0",
7142 + "get-paths": "0.0.7",
7143 + "koa-send": "^5.0.0",
7144 + "mz": "^2.4.0",
7145 + "pretty": "^2.0.0",
7146 + "resolve-path": "^1.4.0"
7147 + },
7148 + "dependencies": {
7149 + "debug": {
7150 + "version": "4.3.3",
7151 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
7152 + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
7153 + "requires": {
7154 + "ms": "2.1.2"
7155 + }
7156 + },
7157 + "ms": {
7158 + "version": "2.1.2",
7159 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
7160 + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
7161 + }
7162 + }
7163 + },
6580 "levn": { 7164 "levn": {
6581 "version": "0.4.1", 7165 "version": "0.4.1",
6582 "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 7166 "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
...@@ -7059,12 +7643,27 @@ ...@@ -7059,12 +7643,27 @@
7059 "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 7643 "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
7060 "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 7644 "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
7061 }, 7645 },
7646 + "pify": {
7647 + "version": "4.0.1",
7648 + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
7649 + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
7650 + },
7062 "prelude-ls": { 7651 "prelude-ls": {
7063 "version": "1.2.1", 7652 "version": "1.2.1",
7064 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 7653 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
7065 "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 7654 "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
7066 "dev": true 7655 "dev": true
7067 }, 7656 },
7657 + "pretty": {
7658 + "version": "2.0.0",
7659 + "resolved": "https://registry.npmjs.org/pretty/-/pretty-2.0.0.tgz",
7660 + "integrity": "sha1-rbx5YLe7/iiaVX3F9zdhmiINBqU=",
7661 + "requires": {
7662 + "condense-newlines": "^0.2.1",
7663 + "extend-shallow": "^2.0.1",
7664 + "js-beautify": "^1.6.12"
7665 + }
7666 + },
7068 "process-nextick-args": { 7667 "process-nextick-args": {
7069 "version": "2.0.1", 7668 "version": "2.0.1",
7070 "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 7669 "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
...@@ -7081,6 +7680,11 @@ ...@@ -7081,6 +7680,11 @@
7081 "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", 7680 "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz",
7082 "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==" 7681 "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g=="
7083 }, 7682 },
7683 + "proto-list": {
7684 + "version": "1.2.4",
7685 + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
7686 + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk="
7687 + },
7084 "protobufjs": { 7688 "protobufjs": {
7085 "version": "6.11.2", 7689 "version": "6.11.2",
7086 "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", 7690 "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz",
...@@ -7110,6 +7714,11 @@ ...@@ -7110,6 +7714,11 @@
7110 "ipaddr.js": "1.9.1" 7714 "ipaddr.js": "1.9.1"
7111 } 7715 }
7112 }, 7716 },
7717 + "pseudomap": {
7718 + "version": "1.0.2",
7719 + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
7720 + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
7721 + },
7113 "punycode": { 7722 "punycode": {
7114 "version": "2.1.1", 7723 "version": "2.1.1",
7115 "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 7724 "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
...@@ -7319,6 +7928,11 @@ ...@@ -7319,6 +7928,11 @@
7319 "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", 7928 "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz",
7320 "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" 7929 "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA=="
7321 }, 7930 },
7931 + "sigmund": {
7932 + "version": "1.0.1",
7933 + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
7934 + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA="
7935 + },
7322 "signal-exit": { 7936 "signal-exit": {
7323 "version": "3.0.6", 7937 "version": "3.0.6",
7324 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", 7938 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 "bcrypt": "^5.0.1", 16 "bcrypt": "^5.0.1",
17 "crypto": "^1.0.1", 17 "crypto": "^1.0.1",
18 "dotenv": "^10.0.0", 18 "dotenv": "^10.0.0",
19 + "ejs": "^3.1.6",
19 "express": "^4.17.1", 20 "express": "^4.17.1",
20 "firebase": "^9.6.0", 21 "firebase": "^9.6.0",
21 "http2": "^3.3.7", 22 "http2": "^3.3.7",
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
27 "koa-passport": "^4.1.4", 28 "koa-passport": "^4.1.4",
28 "koa-router": "^10.1.1", 29 "koa-router": "^10.1.1",
29 "koa-send": "^5.0.1", 30 "koa-send": "^5.0.1",
31 + "koa-views": "^8.0.0",
30 "mongoose": "^6.0.12", 32 "mongoose": "^6.0.12",
31 "nodemailer": "^6.7.1", 33 "nodemailer": "^6.7.1",
32 "passport": "^0.5.0", 34 "passport": "^0.5.0",
......
1 +
2 +
1 require('dotenv').config() 3 require('dotenv').config()
2 const Router = require("@koa/router"); 4 const Router = require("@koa/router");
3 const authCtrl = require("./auth.ctrl"); 5 const authCtrl = require("./auth.ctrl");
...@@ -40,7 +42,7 @@ auth.get('/new', async (ctx) => { ...@@ -40,7 +42,7 @@ auth.get('/new', async (ctx) => {
40 42
41 auth.get('/', async (ctx) => { 43 auth.get('/', async (ctx) => {
42 try{ 44 try{
43 - const user = await User.find({}).sort({email:-1}).exec();//1 오름차순 -1내림차순 45 + const users = await User.find({}).sort({email:-1}).exec();//1 오름차순 -1내림차순
44 ctx.render('users/index', {users}); 46 ctx.render('users/index', {users});
45 }catch(e){ 47 }catch(e){
46 ctx.throw(500, e); 48 ctx.throw(500, e);
...@@ -50,7 +52,7 @@ auth.get('/', async (ctx) => { ...@@ -50,7 +52,7 @@ auth.get('/', async (ctx) => {
50 52
51 53
52 // show 54 // show
53 -auth.get('/:username', async (ctx) => { 55 +auth.get('/:id', async (ctx) => {
54 const user = await User.findOne({_id:ctx.params._id}); 56 const user = await User.findOne({_id:ctx.params._id});
55 ctx.render('users/show', {user}); 57 ctx.render('users/show', {user});
56 }); 58 });
...@@ -58,14 +60,14 @@ auth.get('/:username', async (ctx) => { ...@@ -58,14 +60,14 @@ auth.get('/:username', async (ctx) => {
58 60
59 61
60 // edit 62 // edit
61 - auth.get('/:username/edit', async (ctx) => { 63 + auth.get('/:id/edit', async (ctx) => {
62 const user = await User.findOne({username:ctx.params.username}); 64 const user = await User.findOne({username:ctx.params.username});
63 ctx.render('users/edit', {user:user}); 65 ctx.render('users/edit', {user:user});
64 }); 66 });
65 67
66 68
67 // update // 2 69 // update // 2
68 - auth.post('/:username', async (ctx) => { 70 + auth.post('/:id', async (ctx) => {
69 await User.findOne({username:ctx.params.username}).select('password').exec(); 71 await User.findOne({username:ctx.params.username}).select('password').exec();
70 72
71 73
...@@ -84,15 +86,16 @@ auth.get('/:username', async (ctx) => { ...@@ -84,15 +86,16 @@ auth.get('/:username', async (ctx) => {
84 86
85 87
86 // destroy 88 // destroy
87 - auth.delete('/:username',async (ctx) => {
88 - try{
89 - var username = ctx.params.username;
90 - await User.deleteOne({username:username});
91 - ctx.redirect('/users');
92 - }catch(e){
93 - ctx.throw(500, e);
94 - }
95 - });
96 89
97 90
98 module.exports = auth; 91 module.exports = auth;
92 +
93 +function checkPermission(ctx, next){
94 + User.findOne({username:ctx.params.username}, function(err, user){
95 + if(err) return res.json(err);
96 + if(user.id != req.user.id) return util.noPermission(ctx);
97 +
98 + next();
99 + });
100 + }
101 +
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -5,16 +5,16 @@ const Joi = require('@hapi/joi'); ...@@ -5,16 +5,16 @@ const Joi = require('@hapi/joi');
5 const config = require('../../lib/config'); 5 const config = require('../../lib/config');
6 const { Mongoose } = require('mongoose'); 6 const { Mongoose } = require('mongoose');
7 exports.booklist = async (ctx) => { 7 exports.booklist = async (ctx) => {
8 - let user; 8 +
9 9
10 try { 10 try {
11 - book = await Book.find() 11 + const books = await Book.find({}).sort({createDate: -1}).exec();
12 - .sort({createDate: -1}) 12 + await ctx.render('books/index', {book:books});
13 - .exec(); 13 + console.log('get /book/');
14 - await ctx.render('books/index', {book:book}); 14 + //ctx.body = books;
15 } catch (e) { 15 } catch (e) {
16 return ctx.throw(500, e); 16 return ctx.throw(500, e);
17 - console.log('get /book/booklist'); 17 +
18 } 18 }
19 } 19 }
20 20
...@@ -66,17 +66,13 @@ exports.addBook = async (ctx) => { ...@@ -66,17 +66,13 @@ exports.addBook = async (ctx) => {
66 66
67 exports.getOneBook = async (ctx) => { 67 exports.getOneBook = async (ctx) => {
68 68
69 - const bookid = ctx.request.body._id; 69 + const bookid = ctx.params.id;//bookid by parameter
70 console.log(bookid); 70 console.log(bookid);
71 try { 71 try {
72 const mybook = await Book.findById(bookid).exec(); 72 const mybook = await Book.findById(bookid).exec();
73 const user = await User.findById(mybook.author).exec();//작가정보 73 const user = await User.findById(mybook.author).exec();//작가정보
74 - const author_name = user.nickname;
75 - const bookInfo = {
76 - "author_name":author_name
77 - }
78 - ctx.body = {mybook,author_name:author_name}
79 console.log(mybook) 74 console.log(mybook)
75 + ctx.render('books/show', {book:mybook, user:user});
80 //ctx.body.authorname = user.nickname; 76 //ctx.body.authorname = user.nickname;
81 //ctx.body = mybook; 77 //ctx.body = mybook;
82 } catch (e) { 78 } catch (e) {
...@@ -84,7 +80,8 @@ exports.getOneBook = async (ctx) => { ...@@ -84,7 +80,8 @@ exports.getOneBook = async (ctx) => {
84 } 80 }
85 //const user = await User.findById(mybook.author).exec(); 81 //const user = await User.findById(mybook.author).exec();
86 //ctx.body = mybook; 82 //ctx.body = mybook;
87 - 83 + console.log('책 정보 하나! 얻기 성공');
84 + ctx.status = 200;
88 85
89 }; 86 };
90 87
...@@ -95,16 +92,20 @@ exports.updateBook = async (ctx) => { ...@@ -95,16 +92,20 @@ exports.updateBook = async (ctx) => {
95 const file = ctx.request.files; 92 const file = ctx.request.files;
96 if(ctx.request.body.cover != undefined) // when user add a new pet image 93 if(ctx.request.body.cover != undefined) // when user add a new pet image
97 ctx.request.body.cover = fs.readFileSync(file.image.path); 94 ctx.request.body.cover = fs.readFileSync(file.image.path);
98 - else 95 + else{
99 ctx.request.body.cover = "" 96 ctx.request.body.cover = ""
97 + }
100 var book = ctx.request.body; //require books's _id 98 var book = ctx.request.body; //require books's _id
101 try { 99 try {
102 - const mybook = await Book.findOne({ _id: book._id }); 100 + const mybook = await Book.findOne({ _id: ctx.params.id });
103 - if(ctx.state.user._id == mybook.author){ 101 + if(ctx.state.user._id == mybook.author){//작성한 사람이 맞을 때만
104 - mybook.updateB(book); 102 + await mybook.updateB(book);
105 - ctx.body = book._id; 103 + await ctx.redirect('/api/page/detail/'+ctx.params.id);
106 ctx.status = 200;} 104 ctx.status = 200;}
107 - 105 + else{
106 + console.log('작성자가 아니다. ');
107 + ctx.status = 400;
108 + }
108 } 109 }
109 catch (e) { 110 catch (e) {
110 ctx.throw(500, e); 111 ctx.throw(500, e);
...@@ -116,10 +117,9 @@ exports.updateBook = async (ctx) => { ...@@ -116,10 +117,9 @@ exports.updateBook = async (ctx) => {
116 }; 117 };
117 118
118 119
119 -
120 exports.deleteBook = async (ctx) => { 120 exports.deleteBook = async (ctx) => {
121 121
122 - let bookid = ctx.query.id; 122 + let bookid =ctx.params.id;
123 try { 123 try {
124 124
125 //var foundB = await Book.findById(bookid).exec(); 125 //var foundB = await Book.findById(bookid).exec();
......
...@@ -2,15 +2,153 @@ const Router = require("@koa/router"); ...@@ -2,15 +2,153 @@ const Router = require("@koa/router");
2 const checkLoggedIn = require("../../lib/checkLoggedIn"); 2 const checkLoggedIn = require("../../lib/checkLoggedIn");
3 const bookCtrl = require("./book.ctrl"); 3 const bookCtrl = require("./book.ctrl");
4 const book = new Router(); 4 const book = new Router();
5 +const User = require("../../models/user");
6 +const Book = require("../../models/book");
7 +//북id params로 전달. Render books/show
5 8
6 -book.get('/',bookCtrl.getOneBook); 9 +book.get('/:id', async (ctx) => {
10 + const bookid = ctx.params.id;//bookid by parameter
11 + console.log(bookid);
12 + try {
13 + const book = await Book.findOne({_id:ctx.params.id});
14 + ctx.render('books/show', {book});
15 + //ctx.body.authorname = user.nickname;
16 + //ctx.body = mybook;
17 + } catch (e) {
18 + ctx.throw(500, e);
19 + }
20 + //const user = await User.findById(mybook.author).exec();
21 + //ctx.body = mybook;
22 + console.log('책 정보 하나! 얻기 성공');
23 + ctx.status = 200;
24 +});
7 //mybook=page,title 25 //mybook=page,title
8 //author_name = author name 26 //author_name = author name
9 -book.post('/',checkLoggedIn,bookCtrl.addBook); // add book 27 +book.post('/',checkLoggedIn,async (ctx) => {
10 -book.patch('/', checkLoggedIn, bookCtrl.updateBook); // modify book information 28 +
11 -book.delete('/',checkLoggedIn,bookCtrl.deleteBook); // delete book 29 + const {
12 -book.get('/booklist',bookCtrl.booklist); 30 + title,
13 -book.get('/search',bookCtrl.scrollBook); 31 + author,
32 + contents,
33 + cover,
34 + hashtag,
35 + } = ctx.request.body;
36 +
37 + const schema = Joi.object().keys({
38 + title: Joi.string().required(),
39 + author: Joi.string(),
40 + contents: Joi.string().allow(null, ''),
41 + hashtag: Joi.string().allow(null, ''),
42 + cover: Joi.allow(null, ''),
43 + });
44 + try {
45 + await schema.validateAsync(ctx.request.body);
46 + } catch (err) {
47 + console.log('add book validaton' + err);
48 + ctx.status = 400;
49 + return;
50 + }
51 + ctx.request.body.author = ctx.state.user;
52 + const book = new Book(ctx.request.body);
53 +
54 + try {
55 + book.save(async (err) => {
56 + if (err) throw err;
57 + const user = await User.findById(ctx.state.user._id).exec();
58 + console.log(book._id);
59 + ctx.redirect('/books');
60 + });
61 + } catch (e) {
62 + ctx.throw(500, e);
63 + }
64 + console.log('저장 성공!');
65 + ctx.status = 200;
66 +});
67 +// add book
68 +// redirect posts (create)
69 +
70 +book.patch('/:id', checkLoggedIn, async (ctx) => {
71 + const file = ctx.request.files;
72 + if(ctx.request.body.cover != undefined) // when user add a new pet image
73 + ctx.request.body.cover = fs.readFileSync(file.image.path);
74 + else{
75 + ctx.request.body.cover = ""
76 + }
77 + var book = ctx.request.body; //require books's _id
78 + try {
79 + const mybook = await Book.findOne({ _id: ctx.params.id });
80 + if(ctx.state.user._id == mybook.author){//작성한 사람이 맞을 때만
81 + await mybook.updateB(book);
82 + await ctx.redirect('/api/page/detail/'+ctx.params.id);
83 + ctx.status = 200;}
84 + else{
85 + console.log('작성자가 아니다. ');
86 + ctx.status = 400;
87 + }
88 + }
89 + catch (e) {
90 + ctx.throw(500, e);
91 +
92 + ctx.status = 400;
93 + ctx.body = {
94 + message: "작성자가 아닙니다. " }
95 + }
96 +});// modify book information
97 +//update book rediret:"/books/"+ctx.params.id
98 +//book.id params
99 +book.delete('/:id',checkLoggedIn,async (ctx) => {
100 + let bookid =ctx.params.id;
101 + try {
102 +
103 + //var foundB = await Book.findById(bookid).exec();
104 + //북작가에게서 책 정보 지우기
105 + var author = await User.findById(bookid);//북 작가.
106 + console.log(author);
107 + console.log(author.books);
108 + await User.delBook(ctx.state.user.email,bookid);
109 + //book에 있던 페이지 다 지우기
110 + await Page.deleteMany({"pages":{$in:b.pages}});
111 +
112 +
113 + //최종 book지우기
114 + var b = await Book.deleteOne({_id:bookid});
115 + } catch (e) {
116 + if(e.name === 'CastError') {
117 + ctx.status = 400;
118 + return;
119 + }
120 + }
121 + console.log('delete success');
122 + ctx.body = {
123 + message: "Delete"
124 + }
125 +}); // delete book
126 +// params.id
127 +//redirect('/books')<-index
128 +book.get('/',async (ctx) => {
129 + try {
130 + const books = await Book.find({}).sort({createDate: -1}).exec();
131 + ctx.render('books/index', {books:books});
132 + } catch (e) {
133 + return ctx.throw(500, e);
134 + }
135 + }
136 +);
137 +book.get('/search', async (ctx) => {
138 + const {filter, renewal} = ctx.query
139 +
140 + if(filter === "조회순") { //조회순
141 + try {
142 + const books = await Book.find().sort({'views': -1}).skip(parseInt(renewal)*10).limit(10)
143 + let result = await bookInfo(books);
144 + ctx.status = 200;
145 + ctx.body = result;
146 + } catch (e) {
147 + ctx.throw(500, e);
148 + }
149 + }
150 +});
151 +
14 book.get('/new', async (ctx) => { 152 book.get('/new', async (ctx) => {
15 ctx.render('books/new'); 153 ctx.render('books/new');
16 }); 154 });
......
1 const Router = require("koa-router"); 1 const Router = require("koa-router");
2 -const page = require("./page"); 2 +//const page = require("./page");
3 -const auth = require("./auth"); 3 +//const auth = require("./auth");
4 -const book = require("./book"); 4 +//const book = require("./book");
5 +//const render = require('../index/');
5 const api = new Router(); 6 const api = new Router();
7 +//const path = require('path');
6 8
7 -api.use("/auth", auth.routes());
8 -api.use("/book", book.routes());
9 -api.use("/page", page.routes());
10 9
11 -api.get('/test', (ctx) => (ctx.body = 'hi')); 10 +
12 -module.exports = api; 11 +///api.use("/auth", auth.routes());
12 +//api.use("/book", book.routes());
13 +//api.use("/page", page.routes());
14 +
15 +
16 +
17 +//module.exports = api;
13 18
......
...@@ -4,6 +4,7 @@ const pageCtrl = require("./page.ctrl"); ...@@ -4,6 +4,7 @@ const pageCtrl = require("./page.ctrl");
4 const page = new Router(); 4 const page = new Router();
5 const Page = require("../../models/page"); 5 const Page = require("../../models/page");
6 const index = require('../../../src/index'); 6 const index = require('../../../src/index');
7 +//const render = require('koa-ejs');
7 //Page api 8 //Page api
8 9
9 /* 10 /*
...@@ -32,7 +33,7 @@ page.get('/recipe/scroll', pageCtrl.scrollPage); // video list sorted by 추 ...@@ -32,7 +33,7 @@ page.get('/recipe/scroll', pageCtrl.scrollPage); // video list sorted by 추
32 33
33 34
34 page.get('/new', async (ctx) => { 35 page.get('/new', async (ctx) => {
35 - ctx.render('posts/new'); 36 + await ctx.render('posts/new');
36 }); 37 });
37 38
38 // create 39 // create
...@@ -46,12 +47,13 @@ page.get('/recipe/scroll', pageCtrl.scrollPage); // video list sorted by 추 ...@@ -46,12 +47,13 @@ page.get('/recipe/scroll', pageCtrl.scrollPage); // video list sorted by 추
46 // show 47 // show
47 page.get('/:id', async (ctx, next) => { 48 page.get('/:id', async (ctx, next) => {
48 const page = await Page.findOne({_id:ctx.params.id}); 49 const page = await Page.findOne({_id:ctx.params.id});
49 - ctx.render('posts/show', {page}); 50 + console.log('찾은 페이지',page);
51 + ctx.render('posts/show', {page:page,user:ctx.state.user});
50 }); 52 });
51 53
52 54
53 // update 55 // update
54 -page.post('/:id', async (ctx, next) => { 56 +page.put('/:id', async (ctx, next) => {
55 ctx.body.updatedAt = Date.now(); //2 57 ctx.body.updatedAt = Date.now(); //2
56 const page = await Page.findOneAndUpdate({_id:ctx.params.id}, ctx.body); 58 const page = await Page.findOneAndUpdate({_id:ctx.params.id}, ctx.body);
57 ctx.redirect("/posts/"+ctx.params.id); 59 ctx.redirect("/posts/"+ctx.params.id);
......
1 -
2 -body {
3 - font-family: 'Open Sans', sans-serif;
4 - }
5 - .breadcrumb-item {
6 - font-size: 0.8em !important;
7 - }
8 - .ellipsis{
9 - display: block;
10 - width: 100%;
11 - white-space: nowrap;
12 - overflow: hidden;
13 - text-overflow: ellipsis; /* 1 */
14 - }
15 -
16 - .board-table {
17 - table-layout: fixed;
18 - }
19 - .board-table .date {
20 - width: 100px;
21 - }
22 -
23 - .post-body{
24 - white-space: pre-line; /* 2 */
25 - }
26 - .post-info{
27 - font-size: 0.8em;
28 - }
...\ No newline at end of file ...\ No newline at end of file
...@@ -14,6 +14,11 @@ const app = new Koa(); ...@@ -14,6 +14,11 @@ const app = new Koa();
14 const router = new Router() 14 const router = new Router()
15 const render = require('koa-ejs'); 15 const render = require('koa-ejs');
16 const path = require('path'); 16 const path = require('path');
17 +//const User = require('../models/user');
18 +//const views = require('koa-views');
19 +const book = require('./routes/book');
20 +const auth = require('./routes/user');
21 +const page = require('./routes/page');
17 22
18 const send = require('koa-send'); 23 const send = require('koa-send');
19 var options = { 24 var options = {
...@@ -39,7 +44,7 @@ mongoose.connect(process.env.MONGO_URI).then( ...@@ -39,7 +44,7 @@ mongoose.connect(process.env.MONGO_URI).then(
39 app 44 app
40 .use(router.routes()) 45 .use(router.routes())
41 .use(router.allowedMethods()); 46 .use(router.allowedMethods());
42 - */ 47 +
43 48
44 render(app, { 49 render(app, {
45 root: path.join(__dirname, 'views'), 50 root: path.join(__dirname, 'views'),
...@@ -48,46 +53,64 @@ app ...@@ -48,46 +53,64 @@ app
48 cache: false, 53 cache: false,
49 debug: true 54 debug: true
50 }); 55 });
56 + */
51 // app.use(async function (ctx) { 57 // app.use(async function (ctx) {
52 // await ctx.render('home/welcome'); 58 // await ctx.render('home/welcome');
53 // }); 59 // });
54 app 60 app
55 .use(jwtMiddleware) 61 .use(jwtMiddleware)
56 - .use(bodyParser()) // bodyParser는 라우터 코드보다 상단에 있어야 합니다. 62 + .use(bodyParser()); // bodyParser는 라우터 코드보다 상단에 있어야 합니다.
57 - .use(router.routes()) 63 +
58 - .use(router.allowedMethods()) 64 + render(app, {
59 - .use(passport.initialize()); 65 + root: path.join(__dirname, 'views'),
66 + layout: false,
67 + viewExt: 'ejs',
68 + cache: false,
69 + debug: true
70 +});
60 71
72 +app
73 +.use(router.routes())
74 +.use(router.allowedMethods())
75 +.use(passport.initialize());
61 76
77 + // .use(views(path.join(__dirname, 'views'), {
78 + //extension: 'ejs'
79 +//}))
80 +
81 + //.use(views('views', { map: { html: 'ejs' } }));
62 router.get('/', async ctx =>{ 82 router.get('/', async ctx =>{
63 await ctx.render('home/welcome'); 83 await ctx.render('home/welcome');
64 }); 84 });
65 85
66 router.get('/about', async ctx =>{ 86 router.get('/about', async ctx =>{
67 - await ctx.render('home/about'); 87 + ctx.render('home/about');
68 }); 88 });
69 - 89 +router.get('/auth', async ctx =>{
70 -router.get('/login', async ctx =>{ 90 + ctx.render('users/login');
71 - await ctx.render('users/index');
72 }); 91 });
73 92
74 -router.get('/signup', async ctx =>{ 93 +//router.use('/', api.routes());
75 - await ctx.render('users/new'); 94 +//router.use("/book", require("./routes/book"));
76 -}); 95 +//router.use("/page", require("./routes/page"));
96 +//router.use("/auth", require("./routes/user"));
97 +router.use('/auth', auth.routes());
98 +router.use('/book', book.routes());
99 +router.use('/page', page.routes());
100 +app.use(router.routes()).use(router.allowedMethods());
77 101
78 102
79 103
80 104
81 -/* 105 +//router.get('/', async (ctx, next) => {
82 -router.get('/', async (ctx, next) => { 106 + // const rawContent = fs.readFileSync('index.html').toString('utf8')
83 - const rawContent = fs.readFileSync('index.html').toString('utf8') 107 + //ctx.body = rawContent
84 - ctx.body = rawContent 108 +//})
85 -})*/
86 109
87 110
88 //router.use(api.routes()); 111 //router.use(api.routes());
89 //app.use(router.routes()).use(router.allowedMethods()) 112 //app.use(router.routes()).use(router.allowedMethods())
90 -router.use('/api', api.routes()); 113 +
91 //app.use(router.routes()).use(router.allowedMethods()); 114 //app.use(router.routes()).use(router.allowedMethods());
92 115
93 116
...@@ -95,10 +118,10 @@ http2 ...@@ -95,10 +118,10 @@ http2
95 .createSecureServer(options, app.callback()) 118 .createSecureServer(options, app.callback())
96 .listen(port, () => console.log("listening on port %i", port)); 119 .listen(port, () => console.log("listening on port %i", port));
97 120
98 -/* 121 + /*
99 app.listen(port, function () { 122 app.listen(port, function () {
100 console.log('server listening on port %d', port); 123 console.log('server listening on port %d', port);
101 }); 124 });
125 +*/
102 126
103 127
...\ No newline at end of file ...\ No newline at end of file
104 - */
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -10,3 +10,13 @@ const checkLoggedIn = (ctx, next) => { ...@@ -10,3 +10,13 @@ const checkLoggedIn = (ctx, next) => {
10 module.exports = checkLoggedIn; 10 module.exports = checkLoggedIn;
11 11
12 12
13 + const User = require('../models/user')
14 + const checkPermission = (ctx, next) => {
15 + const user = User.findOne({username:ctx.params.username});
16 + if(user._id != ctx.status.user._id)
17 + return util.noPermission(ctx);
18 + next();
19 + };
20 + module.exports = checkPermission;
21 +
22 +
...\ No newline at end of file ...\ No newline at end of file
......
1 +/* global style */
2 +form label{
3 + padding: 3px;
4 + margin-bottom: 0;
5 + font-weight: 300;
6 + }
7 + form .form-control{
8 + padding: 3px 7px;
9 + font-size: inherit;
10 + line-height: 20px;
11 + height: auto;
12 + border: 1px solid #ccc;
13 + border-radius: 3px;
14 + width: 100%;
15 + }
16 + form fieldset{
17 + margin: 7px 0 1px;
18 + padding: 0px 15px;
19 + }
20 + form .form-group{
21 + margin: 0;
22 + padding-bottom: 6px;
23 + }
24 + .ellipsis{
25 + display: block;
26 + width: 100%;
27 + white-space: nowrap;
28 + overflow: hidden;
29 + text-overflow: ellipsis;
30 + }
31 + .form-horizontal .control-label {
32 + padding-top: 5px;
33 + text-align: left;
34 + }
35 + .buttons {
36 + margin: 7px 0;
37 + padding: 0 5px;
38 + }
39 + .buttons form{
40 + display: inline-block;
41 + }
42 + .buttons .btn-default{
43 + min-width: 55px;
44 + color: #165751;
45 + border: 1px solid #ccc;
46 + border-right: 1px solid #aaa;
47 + border-bottom: 1px solid #aaa;
48 + border-radius: 4px;
49 + padding: 5px 10px;
50 + background-color: #f5f5f5;
51 + font-size: 0.8em;
52 + font-weight: bold;
53 + }
54 + .buttons .btn-default:hover{
55 + text-decoration: none;
56 + position: relative;
57 + top: 1px;
58 + left: 1px;
59 + border: 1px solid #ccc;
60 + border-top: 1px solid #aaa;
61 + border-left: 1px solid #aaa;
62 + }
63 + .contentBox{
64 + border-top: 1px solid #ccc;
65 + border-bottom: 1px solid #ccc;
66 + }
67 + .contentBoxTop {
68 + font-size: 14px;
69 + font-weight: 600;
70 + margin: 0;
71 + border-bottom: 1px solid #ccc;
72 + background-color: #F5F5F5;
73 + padding: 6px 15px;
74 + }
75 +
76 + /* home style */
77 + .home h1{
78 + color: darkseagreen;
79 + }
80 + .home-login{
81 + max-width: 330px;
82 + font-family: 'Open Sans', sans-serif;
83 + font-size: 12px;
84 + }
85 +
86 + /* post style */
87 + .post {
88 + max-width: 670px;
89 + font-family: 'Open Sans', sans-serif;
90 + font-size: 12px;
91 + }
92 + .post h2 {
93 + color: tomato;
94 + text-align: center;
95 + }
96 + .post .post-body {
97 + white-space: pre-line;
98 + padding: 6px 15px 20px;
99 + }
100 + .post .post-info{
101 + font-size: 11px;
102 + margin: 5px;
103 + padding: 5px 10px;
104 + background-color: #E4E4E4;
105 + border: 0 solid black;
106 + border-radius: 5px;
107 + }
108 + .post .post-info>div{
109 + padding: 5px 0;
110 + border-top: 1px dotted #999;
111 + }
112 + .post .post-info>div:first-child{
113 + border-top: none;
114 + }
115 + .post .post-info span{
116 + display: inline-block;
117 + width: 40px;
118 + }
119 + .post-index .posts{
120 + border-top: 1px solid #ccc;
121 + border-bottom: 1px solid #ccc;
122 + table-layout: fixed;
123 + }
124 + .post .posts th,
125 + .post .posts td
126 + {
127 + padding: 7px 5px;
128 + }
129 + .post .posts th:first-child,
130 + .post .posts td:first-child
131 + {
132 + padding-left: 15px;
133 + }
134 + .post .posts thead{
135 + background-color: #F5F5F5;
136 + }
137 + .post .posts thead tr th{
138 + border-bottom: 1px solid #ccc;
139 + }
140 + .post .posts tbody tr:nth-child(odd){
141 + background-color: #F4FFFF;
142 + }
143 + .post .posts tbody .noData{
144 + background-color: #FFFFFF;
145 + text-align: center;
146 + }
147 + .post .posts .author{
148 + text-align: center;
149 + width: 80px;
150 + }
151 + .post .posts .date{
152 + text-align: center;
153 + width: 100px;
154 + padding-right: 15px;
155 + }
156 + .post-new,
157 + .post-edit{
158 + max-width: 520px;
159 + }
160 +
161 + /* user style */
162 + .user {
163 + max-width: 320px;
164 + font-family: 'Open Sans', sans-serif;
165 + font-size: 12px;
166 + }
167 + .user-index ul{
168 + margin: 0;
169 + padding: 3px 12px;
170 + }
171 + .user-index ul:after {
172 + content: "";
173 + display: block;
174 + clear: both;
175 + }
176 + .user-index ul li{
177 + display: inline-block;
178 + list-style-type: none;
179 + }
180 + .user-index ul li a{
181 + display: inline-block;
182 + text-decoration:none;
183 + margin: 3px;
184 + background-color: #eee;
185 + padding: 3px 10px;
186 + border-radius: 3px;
187 + }
188 + .user-index ul li a:hover{
189 + background-color: #ccc;
190 + }
191 + .user-edit hr{
192 + margin-top: 5px;
193 + margin-bottom: 11px;
194 + }
195 + body {
196 + padding: 50px;
197 + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
198 +}
199 +
200 +a {
201 + color: #00B7FF;
202 +}
203 +
204 +.wrapper {
205 + margin-top: 80px;
206 + margin-bottom: 20px;
207 +}
208 +
209 +.form-signin {
210 + max-width: 420px;
211 + padding: 30px 38px 66px;
212 + margin: 0 auto;
213 + background-color: #eee;
214 + border: 3px dotted rgba(0,0,0,0.1);
215 +}
216 +
217 +.form-signin-heading {
218 + text-align:center;
219 + margin-bottom: 30px;
220 +}
221 +
222 +.form-control {
223 + position: relative;
224 + font-size: 16px;
225 + height: auto;
226 + padding: 10px;
227 +}
228 +
229 +input[type="text"] {
230 + margin-bottom: 0px;
231 + border-bottom-left-radius: 0;
232 + border-bottom-right-radius: 0;
233 +}
234 +
235 +input[type="password"] {
236 + margin-bottom: 20px;
237 + border-top-left-radius: 0;
238 + border-top-right-radius: 0;
239 +}
1 +const Router = require("@koa/router");
2 +const checkLoggedIn = require("../../src/lib/checkLoggedIn");
3 +//const bookCtrl = require("./book.ctrl");
4 +const book = new Router();
5 +const User = require("../models/user")
6 +const Book = require("../models/book");
7 +//북id params로 전달. Render books/show
8 +book.get('/:id', async (ctx) => {
9 + const bookid = ctx.params.id;//bookid by parameter
10 + console.log(bookid);
11 + try {
12 + const book = await Book.findOne({_id:ctx.params.id});
13 + ctx.render('books/show', {book});
14 + //ctx.body.authorname = user.nickname;
15 + //ctx.body = mybook;
16 + } catch (e) {
17 + ctx.throw(500, e);
18 + }
19 + //const user = await User.findById(mybook.author).exec();
20 + //ctx.body = mybook;
21 + console.log('책 정보 하나! 얻기 성공');
22 + ctx.status = 200;
23 +});
24 +//mybook=page,title
25 +//author_name = author name
26 +book.post('/',checkLoggedIn,async (ctx) => {
27 +
28 + const {
29 + title,
30 + author,
31 + contents,
32 + cover,
33 + hashtag,
34 + } = ctx.request.body;
35 +
36 + const schema = Joi.object().keys({
37 + title: Joi.string().required(),
38 + author: Joi.string(),
39 + contents: Joi.string().allow(null, ''),
40 + hashtag: Joi.string().allow(null, ''),
41 + cover: Joi.allow(null, ''),
42 + });
43 + try {
44 + await schema.validateAsync(ctx.request.body);
45 + } catch (err) {
46 + console.log('add book validaton' + err);
47 + ctx.status = 400;
48 + return;
49 + }
50 + ctx.request.body.author = ctx.state.user;
51 + const book = new Book(ctx.request.body);
52 +
53 + try {
54 + book.save(async (err) => {
55 + if (err) throw err;
56 + const user = await User.findById(ctx.state.user._id).exec();
57 + console.log(book._id);
58 + ctx.redirect('/books');
59 + });
60 + } catch (e) {
61 + ctx.throw(500, e);
62 + }
63 + console.log('저장 성공!');
64 + ctx.status = 200;
65 +});
66 +// add book
67 +// redirect posts (create)
68 +
69 +book.patch('/:id', checkLoggedIn, async (ctx) => {
70 + const file = ctx.request.files;
71 + if(ctx.request.body.cover != undefined) // when user add a new pet image
72 + ctx.request.body.cover = fs.readFileSync(file.image.path);
73 + else{
74 + ctx.request.body.cover = ""
75 + }
76 + var book = ctx.request.body; //require books's _id
77 + try {
78 + const mybook = await Book.findOne({ _id: ctx.params.id });
79 + if(ctx.state.user._id == mybook.author){//작성한 사람이 맞을 때만
80 + await mybook.updateB(book);
81 + await ctx.redirect('/api/page/detail/'+ctx.params.id);
82 + ctx.status = 200;}
83 + else{
84 + console.log('작성자가 아니다. ');
85 + ctx.status = 400;
86 + }
87 + }
88 + catch (e) {
89 + ctx.throw(500, e);
90 +
91 + ctx.status = 400;
92 + ctx.body = {
93 + message: "작성자가 아닙니다. " }
94 + }
95 +});// modify book information
96 +//update book rediret:"/books/"+ctx.params.id
97 +//book.id params
98 +book.delete('/:id',checkLoggedIn,async (ctx) => {
99 + let bookid =ctx.params.id;
100 + try {
101 +
102 + //var foundB = await Book.findById(bookid).exec();
103 + //북작가에게서 책 정보 지우기
104 + var author = await User.findById(bookid);//북 작가.
105 + console.log(author);
106 + console.log(author.books);
107 + await User.delBook(ctx.state.user.email,bookid);
108 + //book에 있던 페이지 다 지우기
109 + await Page.deleteMany({"pages":{$in:b.pages}});
110 +
111 +
112 + //최종 book지우기
113 + var b = await Book.deleteOne({_id:bookid});
114 + } catch (e) {
115 + if(e.name === 'CastError') {
116 + ctx.status = 400;
117 + return;
118 + }
119 + }
120 + console.log('delete success');
121 + ctx.body = {
122 + message: "Delete"
123 + }
124 +}); // delete book
125 +// params.id
126 +//redirect('/books')<-index
127 +book.get('/',async (ctx) => {
128 + try {
129 + const books = await Book.find({}).sort({createDate: -1}).exec();
130 + ctx.render('books/index', {books:books});
131 + } catch (e) {
132 + return ctx.throw(500, e);
133 + }
134 + }
135 +);
136 +book.get('/search', async (ctx) => {
137 + const {filter, renewal} = ctx.query
138 +
139 + if(filter === "조회순") { //조회순
140 + try {
141 + const books = await Book.find().sort({'views': -1}).skip(parseInt(renewal)*10).limit(10)
142 + let result = await bookInfo(books);
143 + ctx.status = 200;
144 + ctx.body = result;
145 + } catch (e) {
146 + ctx.throw(500, e);
147 + }
148 + }
149 +});
150 +
151 +book.get('/new', async (ctx) => {
152 + ctx.render('books/new');
153 + });
154 +module.exports = book;
...\ No newline at end of file ...\ No newline at end of file
1 +const Router = require("@koa/router");
2 +const checkLoggedIn = require("../../src/lib/checkLoggedIn");
3 +// const pageCtrl = require("./page.ctrl");
4 +
5 +const page = new Router();
6 +const Page = require("../models/page");
7 +//const index = require('../../../src/index');
8 +//const render = require('koa-ejs');
9 +//Page api
10 +
11 +/*
12 +page.get('/',pageCtrl.getPage); // show a list of user's pages
13 +page.post('/',checkLoggedIn,pageCtrl.addPage); // add page
14 +page.patch('/', checkLoggedIn,pageCtrl.updatePage); // modify page information
15 +page.delete('/',checkLoggedIn,pageCtrl.deletePage); // delete book
16 +
17 +page.get('/search', pageCtrl.search); // /search?title=search_query&petType=petType
18 +//page.post('/search/filter', pageCtrl.searchFilter); //아직 구현 안함
19 +page.post('/:id', pageCtrl.detailPage); // detail recipe page
20 +
21 +//page.get('/recipe/slide', pageCtrl.slidRecipe); // 5 recommended videos in main page
22 +
23 +// /recipe/scroll?filter=filter_query&renewal=count (filter_query: 추천순 or 조회순)
24 +page.get('/recipe/scroll', pageCtrl.scrollPage); // video list sorted by 추천순 or 조회순 in main page
25 +*/
26 +
27 +page.get('/tset', async (ctx) => {
28 +
29 + console.log('testtest');
30 +});
31 +
32 + page.get('/', async (ctx) => {
33 +
34 + const page = await Page.find({}).sort({createDate:-1}).exec();
35 + console.log(page);
36 + await ctx.render('posts/index', {page});
37 + });
38 +
39 +
40 + page.get('/new', async (ctx) => {
41 + await ctx.render('posts/new');
42 + });
43 +
44 + // create
45 + page.put('/', checkLoggedIn, async (ctx, next) => {
46 + const {
47 + title,
48 + author,
49 + contents,
50 + cover,
51 + hashtag,
52 + } = ctx.request.body;
53 +
54 + const schema = Joi.object().keys({
55 + title: Joi.string().required(),
56 + author: Joi.string(),
57 + contents: Joi.string().allow(null, ''),
58 + hashtag: Joi.string().allow(null, ''),
59 + cover: Joi.allow(null, ''),
60 + });
61 + try {
62 + await schema.validateAsync(ctx.request.body);
63 + } catch (err) {
64 + console.log('add book validaton' + err);
65 + ctx.status = 400;
66 + return;
67 + }
68 + ctx.request.body.author = ctx.state.user;
69 + const book = new Book(ctx.request.body);
70 +
71 + try {
72 + book.save(async (err) => {
73 + if (err) throw err;
74 + const user = await User.findById(ctx.state.user._id).exec();
75 + console.log(book._id);
76 + ctx.redirect('/page');
77 + });
78 + } catch (e) {
79 + ctx.throw(500, e);
80 + }
81 + console.log('저장 성공!');
82 + ctx.status = 200;
83 +
84 + ctx.redirect('/page');
85 + });
86 +
87 +
88 +
89 + // show
90 + page.get('/:id', async (ctx, next) => {
91 + try{
92 + var id = ctx.params.id;
93 + const page = await Page.findById(id).exec();
94 + await ctx.render('posts/show', {page:page});
95 + ctx.status = 200;
96 + }catch(e){
97 + ctx.throw(500,e);
98 + }
99 +
100 +
101 + });
102 +
103 +
104 +// update
105 +page.patch('/:id',checkLoggedIn, async (ctx, next) => {
106 + const id = ctx.params.id;
107 + if(ctx.request.files != undefined) // when user add a new pet image
108 + ctx.request.body.image = fs.readFileSync(file.image.path);
109 + else
110 + ctx.request.body.image = ""
111 + ctx.body.updateDate = Date.now();
112 + var page = ctx.request.body;
113 + try {
114 + const mypage = await Page.findOne({ _id: id });//require page's _id
115 + if(ctx.state.user._id == mypage.author){
116 + mypage.updateP(page);
117 +
118 + console.log(mypage);
119 + ctx.redirect("/page/"+id);
120 + ctx.status = 200;}
121 +
122 + } catch (e) {
123 + ctx.throw(500, e);
124 + ctx.body = {
125 + message: "작성자가 아닙니다. " }
126 + }
127 + });
128 +
129 + // destroy
130 + page.delete('/:id', async (ctx, next) => {
131 + try{
132 + await Page.deleteOne({_id:ctx.params.id})
133 + ctx.redirect('/page');
134 + }catch(e){
135 + ctx.throw(500, e);
136 + }
137 + });
138 +
139 +
140 +
141 +//page.post('/postinfo', pageCtrl.uploadInfo);
142 +//page.get('/info',pageCtrl.getbyurl);//url로 recipe정보 가져오기 (flutter 내 레시피에서 쓰임.)
143 +module.exports = page;
1 +require('dotenv').config()
2 +const Router = require("@koa/router");
3 +//const authCtrl = require("auth.ctrl");
4 +const checkLoggedIn = require("../../src/lib/checkLoggedIn");
5 +//var passport = require('passport');
6 +const User = require("../models/user");
7 +//var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
8 +const auth = new Router();
9 +
10 +// 회원가입- 로컬 이메일 인증번호 발송 POST auth/signup/email/demand
11 +// 회원가입 이메일 인증번호 확인 POST auth/signup/email/verify
12 +// 로그인 "소셜 로그인
13 +// (페이스북 구글 네이버 카카오)" POST auth/signin/social
14 +// 회원정보갱신 설문이나 설정에서 개인정보 바꾸면 적용 PATCH auth/update/pet
15 +// 회원정보갱신 설문이나 설정에서 개인정보 바꾸면 적용 PATCH auth/update/user
16 +/*
17 +auth.get('/userlist', authCtrl.userlist);
18 +auth.get('/test', authCtrl.test);
19 +auth.post('/signup', authCtrl.signupLocal);
20 +auth.post('/signin', authCtrl.signinLocal);
21 +auth.get('/signout',checkLoggedIn, authCtrl.signout);
22 +auth.get('/check', authCtrl.check2);
23 +auth.delete('/user',checkLoggedIn,authCtrl.Withdrawal); // 회원 탈퇴
24 +auth.post('/validate', authCtrl.exists);
25 +auth.post('/checkpassword', authCtrl.checkPassword);
26 +auth.get('/book',checkLoggedIn,authCtrl.getUserBook);
27 +auth.get('/user', checkLoggedIn,authCtrl.userinfo); // show user information
28 +auth.patch('/user', checkLoggedIn, authCtrl.updateUser); // modify user information
29 +auth.patch('/user/password', authCtrl.changePassword); // change password
30 +auth.post('/find/password', authCtrl.findPassword); // 비밀번호 찾기
31 +auth.get('/favorite',checkLoggedIn, authCtrl.showFavorite); // show a list of user's favorites
32 +auth.post('/favorite',checkLoggedIn, authCtrl.addFavorite); // add favorite
33 +auth.delete('/favorite',checkLoggedIn, authCtrl.delFavorite); // delete favorite
34 +
35 +auth.post('/find/password', authCtrl.findPassword); // 비밀번호 찾기
36 +*/
37 +auth.get('/new', async (ctx) => {
38 + ctx.render('users/new');
39 + });
40 +
41 +auth.get('/test', async (ctx) => {
42 + ctx.render('users/login');
43 + });
44 +
45 +
46 +// show
47 +/*
48 +auth.get('/:id', async (ctx) => {
49 + try{
50 + const user = await User.findOne({_id:ctx.params._id});
51 + ctx.render('users/show', {user});
52 + }catch(e){
53 + ctx.throw(500, e);
54 + console.log(e); }
55 +
56 + });
57 +*/
58 +auth.get('/login', async (ctx) => {
59 +
60 + await ctx.render('home/login')
61 +});
62 +
63 +
64 +
65 + // edit
66 + auth.get('/:id/edit', async (ctx) => {
67 + const user = await User.find({email:ctx.params.email}).exec();
68 + ctx.render('users/edit', {user:user});
69 + });
70 +
71 +
72 + auth.post('/login',async(ctx) =>{
73 + const { email, password } = ctx.request.body;
74 + const errors ='';
75 + //handle error
76 + if (!email || !password) {
77 + ctx.status = 401; //Unauthorized
78 + errors= '비밀번호, 이메일 중 하나가 틀렸습니다. '
79 + return;
80 + }
81 + try {
82 + //const user = User.findOne({ email: email });
83 + const user = await User.findByEmail(email);
84 + //계정없으면 에러처리
85 + console.log(user);
86 + if (!user) {
87 + ctx.status = 401;
88 + return;
89 + }
90 +
91 + const valid = await user.checkPassword(password);
92 + if (!valid) {
93 + ctx.status = 401;
94 + return;
95 + }
96 + ctx.body = await user.serialize();
97 + const token = user.generateToken();
98 + ctx.cookies.set('access_token', token, {
99 + maxAge: 1000 * 60 * 60 * 24 * 7, // 7일
100 + httpOnly: false,
101 + });
102 + ctx.status = 200;
103 + ctx.redirect('/page');
104 + console.log('토큰나옴, 로그인');
105 + } catch (e) {
106 + ctx.throw(500, e);
107 + ctx.redirect('/')
108 + }
109 +
110 + });
111 +
112 + auth.post('/signup',async(ctx)=>{const { email, password, address } = ctx.request.body;
113 + console.log(ctx.request.body);
114 + const schema = Joi.object().keys({
115 + email: Joi.string().min(3).required(),
116 + password: Joi.string().required(),
117 + phone: Joi.string().allow(null, ''),
118 + nickname:Joi.string().allow(null, '')
119 + });
120 +
121 + //검증 결과
122 + try {
123 + const value = await schema.validateAsync(ctx.request.body);
124 + } catch (err) {
125 + console.log(err);
126 + ctx.status = 400;
127 + return;
128 + }
129 +
130 + try {
131 + // email 이미 존재하는지 확인
132 + const exists = await User.findByEmail(email);
133 + if (exists) {
134 + ctx.status = 409; // Conflict
135 + return;
136 + }
137 +
138 + let account = null;
139 + try {
140 + account = await User.localRegister(ctx.request.body);
141 + } catch (e) {
142 + ctx.throw(500, e);
143 + }
144 +
145 + let token = null;
146 + try {
147 + token = await account.generateToken();
148 + console.log('token ok');
149 + } catch (e) {
150 + ctx.throw(500, e);
151 + }
152 + ctx.cookies.set('access_token', token, { maxAge: 1000 * 60 * 60 * 24 * 7 ,httpOnly: true,});
153 + console.log('set cookie ok');
154 +
155 + // 응답할 데이터에서 hashedPassword 필드 제거
156 + ctx.status = 200;
157 + await ctx.render('users/new');
158 + } catch (e) {
159 + ctx.throw(500, e);
160 + }});
161 +
162 + // update // 2
163 + auth.post('/:id', async (ctx) => {
164 + await User.findOne({username:ctx.params.username}).select('password').exec();
165 +
166 +
167 + // update user object
168 + user.originalPassword = user.password;
169 + user.password = ctx.body.newPassword? ctx.body.newPassword : user.password; // 2-3
170 + for(var p in ctx.body) // 2-4
171 + user[p] = ctx.body[p];
172 +
173 +
174 + // save updated user
175 + await user.save();
176 +
177 + ctx.redirect('/users/'+user.nickname);
178 + });
179 +
180 +
181 + // destroy
182 + auth.get('/logout', async (ctx) => {
183 + ctx.cookies.set('access_token');
184 + ctx.status = 204;
185 + ctx.redirect('/');
186 + });
187 +
188 +
189 +module.exports = auth;
190 +
191 +function checkPermission(ctx, next){
192 + User.findOne({username:ctx.params.username}, function(err, user){
193 + if(err) return res.json(err);
194 + if(user.id != req.user.id) return util.noPermission(ctx);
195 +
196 + next();
197 + });
198 + }
...\ No newline at end of file ...\ No newline at end of file
1 +var util = {};
2 +
3 +util.parseError = function(errors){
4 + var parsed = {};
5 + if(errors.name == 'ValidationError'){
6 + for(var name in errors.errors){
7 + var validationError = errors.errors[name];
8 + parsed[name] = { message:validationError.message };
9 + }
10 + }
11 + else if(errors.code == '11000' && errors.errmsg.indexOf('username') > 0) {
12 + parsed.username = { message:'This username already exists!' };
13 + }
14 + else {
15 + parsed.unhandled = JSON.stringify(errors);
16 + }
17 + return parsed;
18 +}
19 +
20 +util.isLoggedin = function(req, res, next){
21 + if(req.isAuthenticated()){
22 + next();
23 + }
24 + else {
25 + req.flash('errors', {login:'Please login first'});
26 + res.redirect('/login');
27 + }
28 +}
29 +
30 +util.noPermission = function(ctx){
31 + ctx.request.flash('errors', {login:"You don't have permission"});
32 + ctx.request.logout();
33 + ctx.request.redirect('/login');
34 +}
35 +
36 +module.exports = util;
...\ No newline at end of file ...\ No newline at end of file
...@@ -9,26 +9,26 @@ ...@@ -9,26 +9,26 @@
9 <nav aria-label="breadcrumb"> 9 <nav aria-label="breadcrumb">
10 <ol class="breadcrumb p-1 pl-2 pr-2"> 10 <ol class="breadcrumb p-1 pl-2 pr-2">
11 <li class="breadcrumb-item"><a href="/">Home</a></li> 11 <li class="breadcrumb-item"><a href="/">Home</a></li>
12 - <li class="breadcrumb-item"><a href="/api/page">Board</a></li> 12 + <li class="breadcrumb-item"><a href="/api/page">Page</a></li>
13 - <li class="breadcrumb-item"><a href="/api/page/<%= page._id %>"><%= page.title %></a></li> 13 + <li class="breadcrumb-item"><a href="/api/book/<%= book._id %>"><%= book.title %></a></li>
14 <li class="breadcrumb-item active" aria-current="page">Edit Post</li> 14 <li class="breadcrumb-item active" aria-current="page">Edit Post</li>
15 </ol> 15 </ol>
16 </nav> 16 </nav>
17 17
18 - <form action="/api/page/<%= page._id %>?_method=put" method="post"> 18 + <form action="/api/book/<%= book._id %>?_method=patch" method="patch">
19 19
20 <div class="form-group"> 20 <div class="form-group">
21 <label for="title">Title</label> 21 <label for="title">Title</label>
22 - <input type="text" id="title" name="title" value="<%= page.title %>" class="form-control"> 22 + <input type="text" id="title" name="title" value="<%= book.title %>" class="form-control">
23 </div> 23 </div>
24 24
25 <div class="form-group"> 25 <div class="form-group">
26 <label for="body">Body</label> 26 <label for="body">Body</label>
27 - <textarea id="body" name="body" rows="5" class="form-control"><%= post.contents %></textarea> 27 + <textarea id="body" name="body" rows="5" class="form-control"><%= book.contents %></textarea>
28 </div> 28 </div>
29 29
30 <div> 30 <div>
31 - <a class="btn btn-primary" href="/api/page/<%= page._id %>">Back</a> 31 + <a class="btn btn-primary" href="/api/book/<%= book._id %>">Back</a>
32 <button type="submit" class="btn btn-primary">Submit</button> 32 <button type="submit" class="btn btn-primary">Submit</button>
33 </div> 33 </div>
34 34
......
1 +<!-- views/books/index.ejs -->
1 <!DOCTYPE html> 2 <!DOCTYPE html>
2 <html> 3 <html>
3 <head> 4 <head>
...@@ -20,18 +21,18 @@ ...@@ -20,18 +21,18 @@
20 </thead> 21 </thead>
21 22
22 <tbody> 23 <tbody>
23 - <% if(page == null || page.length == 0){ %> 24 + <% if(books == null || books.length == 0){ %>
24 <tr> 25 <tr>
25 <td colspan=2> There is no data to show :( </td> 26 <td colspan=2> There is no data to show :( </td>
26 </tr> 27 </tr>
27 <% } %> 28 <% } %>
28 - <% page.forEach(function(page) { %> 29 + <% books.forEach(function(book) { %>
29 <tr> 30 <tr>
30 <td> 31 <td>
31 - <a href="/api/page/<%= page._id %>"><div class="ellipsis"><%= page.title %></div></a> 32 + <a href="/api/book/<%= book._id %>"><div class="ellipsis"><%= book.title %></div></a>
32 </td> 33 </td>
33 <td class="date"> 34 <td class="date">
34 - <span data-date="<%= page.createDate %>"></span> <!-- 1 --> 35 + <span data-date="<%= book.createDate %>"></span> <!-- 1 -->
35 </td> 36 </td>
36 </tr> 37 </tr>
37 <% }) %> 38 <% }) %>
...@@ -40,7 +41,7 @@ ...@@ -40,7 +41,7 @@
40 </table> 41 </table>
41 42
42 <div> 43 <div>
43 - <a class="btn btn-primary" href="/api/page/new">New</a> 44 + <a class="btn btn-primary" href="/api/book/new">New</a>
44 </div> 45 </div>
45 46
46 </div> 47 </div>
......
...@@ -11,12 +11,12 @@ ...@@ -11,12 +11,12 @@
11 <nav aria-label="breadcrumb"> <!-- 1 --> 11 <nav aria-label="breadcrumb"> <!-- 1 -->
12 <ol class="breadcrumb p-1 pl-2 pr-2"> 12 <ol class="breadcrumb p-1 pl-2 pr-2">
13 <li class="breadcrumb-item"><a href="/">Home</a></li> 13 <li class="breadcrumb-item"><a href="/">Home</a></li>
14 - <li class="breadcrumb-item"><a href="/api/page">Board</a></li> 14 + <li class="breadcrumb-item"><a href="/api/page">Page</a></li>
15 - <li class="breadcrumb-item active" aria-current="page">New Post</li> 15 + <li class="breadcrumb-item active" aria-current="page">New Book</li>
16 </ol> 16 </ol>
17 </nav> 17 </nav>
18 18
19 - <form action="/api/page/" method="post"> 19 + <form action="/api/book" method="post">
20 20
21 <div class="form-group"> 21 <div class="form-group">
22 <label for="title">Title</label> 22 <label for="title">Title</label>
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
29 </div> 29 </div>
30 30
31 <div> 31 <div>
32 - <a class="btn btn-primary" href="/api/page">Back</a> 32 + <a class="btn btn-primary" href="/api/book">Back</a>
33 <button type="submit" class="btn btn-primary">Submit</button> 33 <button type="submit" class="btn btn-primary">Submit</button>
34 </div> 34 </div>
35 35
......
...@@ -11,24 +11,24 @@ ...@@ -11,24 +11,24 @@
11 <nav aria-label="breadcrumb"> 11 <nav aria-label="breadcrumb">
12 <ol class="breadcrumb p-1 pl-2 pr-2"> 12 <ol class="breadcrumb p-1 pl-2 pr-2">
13 <li class="breadcrumb-item"><a href="/">Home</a></li> 13 <li class="breadcrumb-item"><a href="/">Home</a></li>
14 - <li class="breadcrumb-item"><a href="/api/book">Book</a></li> 14 + <li class="breadcrumb-item"><a href="/api/page">Page</a></li>
15 - <li class="breadcrumb-item active" aria-current="page"><%= page.title %></li> 15 + <li class="breadcrumb-item active" aria-current="page"><%= book.title %></li>
16 </ol> 16 </ol>
17 </nav> 17 </nav>
18 18
19 <div class="card"> 19 <div class="card">
20 - <h5 class="card-header p-2"><%= page.title %></h5> 20 + <h5 class="card-header p-2"><%= book.title %></h5>
21 <div class="row"> <!-- 1 --> 21 <div class="row"> <!-- 1 -->
22 22
23 <div class="col-md-7 col-lg-8 col-xl-9 order-sm-2 order-md-1"> <!-- 1 --> 23 <div class="col-md-7 col-lg-8 col-xl-9 order-sm-2 order-md-1"> <!-- 1 -->
24 - <div class="post-body p-2"><%= page.contents %></div> 24 + <div class="post-body p-2"><%= book.contents %></div>
25 </div> 25 </div>
26 26
27 <div class="col-md-5 col-lg-4 col-xl-3 order-sm-1 order-md-2"> <!-- 1 --> 27 <div class="col-md-5 col-lg-4 col-xl-3 order-sm-1 order-md-2"> <!-- 1 -->
28 <div class="post-info card m-2 p-2"> 28 <div class="post-info card m-2 p-2">
29 - <div><span>Created</span> : <span data-date-time="<%= page.createDate %>"></span></div> <!-- 2 --> 29 + <div><span>Created</span> : <span data-date-time="<%= book.createDate %>"></span></div> <!-- 2 -->
30 - <% if(page.updateDate) { %> 30 + <% if(book.createDate) { %>
31 - <div><span>Updated</span> : <span data-date-time="<%= page.updateDate %>"></span></div> <!-- 2 --> 31 + <div><span>Updated</span> : <span data-date-time="<%= book.updateDate %>"></span></div> <!-- 2 -->
32 <% } %> 32 <% } %>
33 </div> 33 </div>
34 </div> 34 </div>
...@@ -37,9 +37,9 @@ ...@@ -37,9 +37,9 @@
37 </div> 37 </div>
38 38
39 <div class="mt-3"> 39 <div class="mt-3">
40 - <a class="btn btn-primary" href="/api/page">Back</a> 40 + <a class="btn btn-primary" href="/api/book">Back</a>
41 - <a class="btn btn-primary" href="/api/page/<%= page._id %>/edit">Edit</a> 41 + <a class="btn btn-primary" href="/api/book/<%= book._id %>/edit">Edit</a>
42 - <form action="/api/page/<%= page._id %>?_method=delete" method="post" class="d-inline"> 42 + <form action="/api/book/<%= book._id %>?_method=delete" method="post" class="d-inline">
43 <a class="btn btn-primary" href="javascript:void(0)" onclick="confirm('Do you want to delete this?')?this.parentElement.submit():null;">Delete</a> 43 <a class="btn btn-primary" href="javascript:void(0)" onclick="confirm('Do you want to delete this?')?this.parentElement.submit():null;">Delete</a>
44 </form> 44 </form>
45 </div> 45 </div>
......
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <html> 2 <html>
3 - <head> 3 +<head>
4 - <%- include('../partials/head') %> 4 + <meta charset="utf-8">
5 - </head> 5 + <meta http-equiv="x-ua-compatible" content="ie=edge">
6 - <body> 6 + <title>Login Example</title>
7 - <%- include('../partials/nav') %> 7 + <meta name="description" content="">
8 - 8 + <meta name="viewport" content="width=device-width, initial-scale=1">
9 +
10 + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
11 + <link rel="stylesheet" href="../stylesheets/style.css">
12 +
13 + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
14 + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
15 +</head>
16 +<body>
9 <div class="container"> 17 <div class="container">
18 + <div class="wrapper">
19 + <form action="/auth/login" method="post" name="Login_Form" class="form-signin">
20 + <h3 class="form-signin-heading">Welcome! Please Sign In</h3>
10 21
11 - <h3 class="mb-3">Login</h3> 22 + <input type="text" class="form-control" name="email" placeholder="Email Address" required="" autofocus="" />
12 - 23 + <input type="password" class="form-control" name="password" placeholder="Password" required=""/>
13 - <form class="user-form" action="/login" method="post">
14 -
15 - <div class="form-group row">
16 - <label for="username" class="col-sm-3 col-form-label">Username</label>
17 - <div class="col-sm-9">
18 - <input type="text" id="username" name="username" value="<%= username %>" class="form-control <%= (errors.username)?'is-invalid':'' %>">
19 - <% if(errors.username){ %>
20 - <span class="invalid-feedback"><%= errors.username %></span>
21 - <% } %>
22 - </div>
23 - </div>
24 -
25 - <div class="form-group row">
26 - <label for="password" class="col-sm-3 col-form-label">Password</label>
27 - <div class="col-sm-9">
28 - <input type="password" id="password" name="password" value="" class="form-control <%= (errors.password)?'is-invalid':'' %>">
29 - <% if(errors.password){ %>
30 - <span class="invalid-feedback"><%= errors.password %></span>
31 - <% } %>
32 - </div>
33 - </div>
34 -
35 - <% if(errors.login){ %>
36 - <div class="invalid-feedback d-block"><%= errors.login %></div>
37 - <% } %>
38 -
39 - <div class="mt-3">
40 - <input class="btn btn-primary" type="submit" value="Submit">
41 - </div>
42 24
25 + <button class="btn btn-lg btn-primary btn-block" name="Submit" value="Login" type="Submit">Login</button>
43 </form> 26 </form>
44 -
45 </div> 27 </div>
46 - </body> 28 + </div>
29 +</body>
47 </html> 30 </html>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -12,6 +12,6 @@ ...@@ -12,6 +12,6 @@
12 <link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet"> 12 <link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
13 13
14 <!-- my css --> 14 <!-- my css -->
15 -<script src="/src/api/page/script.js"></script> 15 +<script src="/src/public/js/script.js"></script>
16 16
17 <title>My Website</title> 17 <title>My Website</title>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -8,13 +8,13 @@ ...@@ -8,13 +8,13 @@
8 <ul class="navbar-nav"> 8 <ul class="navbar-nav">
9 <li class="nav-item"><a href="/" class="nav-link">Home</a></li> 9 <li class="nav-item"><a href="/" class="nav-link">Home</a></li>
10 <li class="nav-item"><a href="/about" class="nav-link">About</a></li> 10 <li class="nav-item"><a href="/about" class="nav-link">About</a></li>
11 - <li class="nav-item"><a href="/api/book" class="nav-link">Book</a></li> 11 + <li class="nav-item"><a href="/book" class="nav-link">Book</a></li>
12 - <li class="nav-item"><a href="/api/page" class="nav-link">Page</a></li> 12 + <li class="nav-item"><a href="/page" class="nav-link">Page</a></li>
13 </ul> 13 </ul>
14 <ul class="navbar-nav ml-auto"> 14 <ul class="navbar-nav ml-auto">
15 15
16 - <li class="nav-item"><a href="/api/auth" class="nav-link">Sign Up</a></li> 16 + <li class="nav-item"><a href="/auth/new" class="nav-link">Sign Up</a></li>
17 - <li class="nav-item"><a href="/api/auth/new" class="nav-link">Login</a></li> 17 + <li class="nav-item"><a href="/auth/login" class="nav-link">Login</a></li>
18 18
19 </ul> 19 </ul>
20 </div> 20 </div>
......
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
11 <nav aria-label="breadcrumb"> 11 <nav aria-label="breadcrumb">
12 <ol class="breadcrumb p-1 pl-2 pr-2"> 12 <ol class="breadcrumb p-1 pl-2 pr-2">
13 <li class="breadcrumb-item"><a href="/">Home</a></li> 13 <li class="breadcrumb-item"><a href="/">Home</a></li>
14 - <li class="breadcrumb-item"><a href="/api/page">Board</a></li> 14 + <li class="breadcrumb-item"><a href="/book">Book</a></li>
15 - <li class="breadcrumb-item"><a href="/api/page/<%= page._id %>"><%= page.title %></a></li> 15 + <li class="breadcrumb-item"><a href="/page/<%= page._id %>"><%= page.title %></a></li>
16 <li class="breadcrumb-item active" aria-current="page">Edit Post</li> 16 <li class="breadcrumb-item active" aria-current="page">Edit Post</li>
17 </ol> 17 </ol>
18 </nav> 18 </nav>
19 19
20 - <form action="/api/page/<%= page._id %>?_method=put" method="post"> 20 + <form action="/page<%= page._id %>?_method=put" method="patch">
21 21
22 <div class="form-group"> 22 <div class="form-group">
23 <label for="title">Title</label> 23 <label for="title">Title</label>
...@@ -26,11 +26,11 @@ ...@@ -26,11 +26,11 @@
26 26
27 <div class="form-group"> 27 <div class="form-group">
28 <label for="body">Body</label> 28 <label for="body">Body</label>
29 - <textarea id="body" name="body" rows="5" class="form-control"><%= post.contents %></textarea> 29 + <textarea id="body" name="body" rows="5" class="form-control"><%= page.contents %></textarea>
30 </div> 30 </div>
31 31
32 <div> 32 <div>
33 - <a class="btn btn-primary" href="/api/page/<%= page._id %>">Back</a> 33 + <a class="btn btn-primary" href="/page/<%= page._id %>">Back</a>
34 <button type="submit" class="btn btn-primary">Submit</button> 34 <button type="submit" class="btn btn-primary">Submit</button>
35 </div> 35 </div>
36 36
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
30 <% page.forEach(function(page) { %> 30 <% page.forEach(function(page) { %>
31 <tr> 31 <tr>
32 <td> 32 <td>
33 - <a href="/api/page/<%= page._id %>"><div class="ellipsis"><%= page.title %></div></a> 33 + <a href="/page/<%= page._id %>"><div class="ellipsis"><%= page.title %></div></a>
34 </td> 34 </td>
35 <td class="date"> 35 <td class="date">
36 <span data-date="<%= page.createDate %>"></span> <!-- 1 --> 36 <span data-date="<%= page.createDate %>"></span> <!-- 1 -->
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
42 </table> 42 </table>
43 43
44 <div> 44 <div>
45 - <a class="btn btn-primary" href="/api/page/new">New</a> 45 + <a class="btn btn-primary" href="/page/new">New</a>
46 </div> 46 </div>
47 47
48 </div> 48 </div>
......
...@@ -11,12 +11,12 @@ ...@@ -11,12 +11,12 @@
11 <nav aria-label="breadcrumb"> <!-- 1 --> 11 <nav aria-label="breadcrumb"> <!-- 1 -->
12 <ol class="breadcrumb p-1 pl-2 pr-2"> 12 <ol class="breadcrumb p-1 pl-2 pr-2">
13 <li class="breadcrumb-item"><a href="/">Home</a></li> 13 <li class="breadcrumb-item"><a href="/">Home</a></li>
14 - <li class="breadcrumb-item"><a href="/api/page">Board</a></li> 14 + <li class="breadcrumb-item"><a href="/page">Board</a></li>
15 <li class="breadcrumb-item active" aria-current="page">New Post</li> 15 <li class="breadcrumb-item active" aria-current="page">New Post</li>
16 </ol> 16 </ol>
17 </nav> 17 </nav>
18 18
19 - <form action="/api/page/" method="post"> 19 + <form action="/page" method="post">
20 20
21 <div class="form-group"> 21 <div class="form-group">
22 <label for="title">Title</label> 22 <label for="title">Title</label>
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
29 </div> 29 </div>
30 30
31 <div> 31 <div>
32 - <a class="btn btn-primary" href="/api/page">Back</a> 32 + <a class="btn btn-primary" href="/page">Back</a>
33 <button type="submit" class="btn btn-primary">Submit</button> 33 <button type="submit" class="btn btn-primary">Submit</button>
34 </div> 34 </div>
35 35
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
5 <%- include('../partials/head') %> 5 <%- include('../partials/head') %>
6 </head> 6 </head>
7 <body> 7 <body>
8 +
8 <%- include('../partials/nav') %> 9 <%- include('../partials/nav') %>
9 10
10 <div class="container mb-3"> 11 <div class="container mb-3">
...@@ -12,7 +13,7 @@ ...@@ -12,7 +13,7 @@
12 <nav aria-label="breadcrumb"> 13 <nav aria-label="breadcrumb">
13 <ol class="breadcrumb p-1 pl-2 pr-2"> 14 <ol class="breadcrumb p-1 pl-2 pr-2">
14 <li class="breadcrumb-item"><a href="/">Home</a></li> 15 <li class="breadcrumb-item"><a href="/">Home</a></li>
15 - <li class="breadcrumb-item"><a href="/api/book">Book</a></li> 16 + <li class="breadcrumb-item"><a href="/page">Page</a></li>
16 <li class="breadcrumb-item active" aria-current="page"><%= page.title %></li> 17 <li class="breadcrumb-item active" aria-current="page"><%= page.title %></li>
17 </ol> 18 </ol>
18 </nav> 19 </nav>
...@@ -38,10 +39,10 @@ ...@@ -38,10 +39,10 @@
38 </div> 39 </div>
39 40
40 <div class="mt-3"> 41 <div class="mt-3">
41 - <a class="btn btn-primary" href="/api/page">Back</a> 42 + <a class="btn btn-primary" href="/page">Back</a>
42 - <a class="btn btn-primary" href="/api/page/<%= page._id %>/edit">Edit</a> 43 + <a class="btn btn-primary" href="/page/<%= page._id %>/edit">Edit</a>
43 - <form action="/api/page/<%= page._id %>?_method=delete" method="post" class="d-inline"> 44 + <form action="/page/<%= page._id %>/_method=delete" method="post" class="d-inline">
44 - <a class="btn btn-primary" href="javascript:void(0)" onclick="confirm('Do you want to delete this?')?this.parentElement.submit():null;">Delete</a> 45 + <a class="btn btn-primary" href="#" onclick="confirm('Do you want to delete this?')?this.parentElement.submit():null;">Delete</a>
45 </form> 46 </form>
46 </div> 47 </div>
47 48
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
11 11
12 <h3 class="mb-3">Edit User</h3> 12 <h3 class="mb-3">Edit User</h3>
13 13
14 - <form action="/api/auth/users/<%= user.username %>?_method=put" method="post"> 14 + <form action="/auth/users/<%= user.username %>?_method=put" method="post">
15 15
16 <div class="form-group row"> 16 <div class="form-group row">
17 <label for="currentPassword" class="col-sm-3 col-form-label">Current Password*</label> 17 <label for="currentPassword" class="col-sm-3 col-form-label">Current Password*</label>
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
62 </p> 62 </p>
63 63
64 <div class="buttons"> 64 <div class="buttons">
65 - <a class="btn btn-primary" href="/api/auth/users/<%= user.username %>">Back</a> 65 + <a class="btn btn-primary" href="/auth/users/<%= user.username %>">Back</a>
66 <button type="submit" class="btn btn-primary">Submit</button> 66 <button type="submit" class="btn btn-primary">Submit</button>
67 </div> 67 </div>
68 68
......
1 -
2 -<!DOCTYPE html>
3 -<html>
4 - <head>
5 - <%- include('../partials/head') %>
6 - </head>
7 - <body>
8 - <%- include('../partials/nav') %>
9 -
10 - <div class="container mb-3">
11 -
12 - <h3 class="mb-3">Users</h3>
13 -
14 - <ul class="list-group">
15 - <% if(user == null || user.length == 0){ %>
16 - <li class="list-group-item"> There is no user yet.</li>
17 - <% } %>
18 - <% user.forEach(function(user) { %>
19 - <li class="list-group-item">
20 - <a href="/api/auth/userlist/<%= user._id %>"><%= user.nickname %></a>
21 - </li>
22 - <% }) %>
23 - </ul>
24 -
25 - </div>
26 - </body>
27 -</html>
...\ No newline at end of file ...\ No newline at end of file
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
12 12
13 <h3 class="contentBoxTop mb-3">New User</h3> 13 <h3 class="contentBoxTop mb-3">New User</h3>
14 14
15 - <form action="/api/auth/signin" method="post"> 15 + <form action="/auth/signin" method="post">
16 16
17 <div class="form-group row"> 17 <div class="form-group row">
18 <label for="nickname" class="col-sm-3 col-form-label">Username*</label> 18 <label for="nickname" class="col-sm-3 col-form-label">Username*</label>
......
...@@ -10,28 +10,23 @@ ...@@ -10,28 +10,23 @@
10 10
11 <div class="container mb-3"> 11 <div class="container mb-3">
12 12
13 - <h3 class="contentBoxTop"><%= user.nickname</h3> 13 + <h3 class="contentBoxTop">usefname</h3>
14 14
15 <form class="user-form" action="/users" method="post"> 15 <form class="user-form" action="/users" method="post">
16 <fieldset disabled> 16 <fieldset disabled>
17 - <div class="form-group row"> 17 +
18 - <label for="name" class="col-sm-3 col-form-label">Name</label>
19 - <div class="col-sm-9">
20 - <input class="form-control" type="text" id="name" name="name" value="<%= user.name %>">
21 - </div>
22 - </div>
23 <div class="form-group row"> 18 <div class="form-group row">
24 <label for="email" class="col-sm-3 col-form-label">Email</label> 19 <label for="email" class="col-sm-3 col-form-label">Email</label>
25 <div class="col-sm-9"> 20 <div class="col-sm-9">
26 - <input class="form-control" type="text" id="email" name="email" value="<%= user.email %>"> 21 + <input class="form-control" type="text" id="email" name="email" value="<%= 9 %>">
27 </div> 22 </div>
28 </div> 23 </div>
29 </fieldset> 24 </fieldset>
30 </form> 25 </form>
31 26
32 <div> 27 <div>
33 - <a class="btn btn-primary" href="/api/auth/users">Back</a> 28 + <a class="btn btn-primary" href="/auth/users">Back</a>
34 - <a class="btn btn-primary" href="/api/auth/users/<%= user.email %>/edit">Edit</a> 29 + <a class="btn btn-primary" href="/auth/users/<%= user.email %>/edit">Edit</a>
35 <form action="/users/<%= user.email %>?_method=delete" method="post" class="d-inline"> 30 <form action="/users/<%= user.email %>?_method=delete" method="post" class="d-inline">
36 <a class="btn btn-primary" href="javascript:void(0)" onclick="confirm('Do you want to delete this?')?this.parentElement.submit():null;">Delete</a> 31 <a class="btn btn-primary" href="javascript:void(0)" onclick="confirm('Do you want to delete this?')?this.parentElement.submit():null;">Delete</a>
37 </form> 32 </form>
......