박유빈

seperate back and front code

1 +module.exports = {
2 + "extends": "standard",
3 + "rules": {
4 + "indent": [
5 + "error",
6 + 4
7 + ],
8 + "semi": [
9 + "error",
10 + "always"
11 + ],
12 + "no-trailing-spaces": 0,
13 + "keyword-spacing": 0,
14 + "no-unused-vars": 1,
15 + "no-multiple-empty-lines": 0,
16 + "space-before-function-paren": 0,
17 + "eol-last": 0
18 + }
19 +};
...\ No newline at end of file ...\ No newline at end of file
1 +/node_modules
2 +.env
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + // Use IntelliSense to learn about possible attributes.
3 + // Hover to view descriptions of existing attributes.
4 + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 + "version": "0.2.0",
6 + "configurations": [
7 + {
8 + "type": "pwa-node",
9 + "request": "launch",
10 + "name": "Launch Program",
11 + "skipFiles": [
12 + "<node_internals>/**"
13 + ],
14 + "program": "${workspaceFolder}/src/api/book/book.ctrl.js",
15 + "outFiles": [
16 + "${workspaceFolder}/**/*.js"
17 + ]
18 + }
19 + ]
20 +}
...\ No newline at end of file ...\ No newline at end of file
1 +-----BEGIN CERTIFICATE-----
2 +MIIDmTCCAoECFA0G8CsoOzEJaSus1d0/oC6+WzOcMA0GCSqGSIb3DQEBCwUAMIGI
3 +MQswCQYDVQQGEwJLcjEOMAwGA1UECAwFU2VvdWwxETAPBgNVBAcMCEd3YW5ha0d1
4 +MQswCQYDVQQKDAJUdzERMA8GA1UECwwIVHdTaXN0ZXIxETAPBgNVBAMMCGxpa2Uu
5 +Y29tMSMwIQYJKoZIhvcNAQkBFhR5b29iaW5wYXJrQGtodS5hYy5rcjAeFw0yMTEx
6 +MTAwNTAzNDhaFw0zMTExMDgwNTAzNDhaMIGIMQswCQYDVQQGEwJLcjEOMAwGA1UE
7 +CAwFU2VvdWwxETAPBgNVBAcMCEd3YW5ha0d1MQswCQYDVQQKDAJUdzERMA8GA1UE
8 +CwwIVHdTaXN0ZXIxETAPBgNVBAMMCGxpa2UuY29tMSMwIQYJKoZIhvcNAQkBFhR5
9 +b29iaW5wYXJrQGtodS5hYy5rcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
10 +ggEBANHhAjf8HAfdy0v15teX1ENK3eaLF14GiguOc5/KmaAYYj1nIl7LGdjiumB6
11 +VJT0elRIAx1DCGoPDN8d5Dhfrpftblv7lPFUOVKpI6Rjcl6EVRCOm3I6TehXazg9
12 +ACdHRA/8uxLG8MFKsmAVh1wQXGnBVoobgZyNDq3yU4d0y6paCvHCVVBTIB/Mdikp
13 +vLiDRfrB9m6L5YC6Aux6Dn2nfX+GTUvxXzks4RoDtJAiklnfczgFDVc8oN6ZMplq
14 +A4TPF67TLsY071x2XQIpUruWleWo4MdZPIQr/ex2WFvbJT8+Y6wsEfD2AgCxBBuT
15 +hVYhmsFaAf0fYv+ftQwd60oBdoMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAPIuB
16 +rauwsJoEQvMH6G4b7AXyyKytfmOkK3e8RSvNeeu/IUoAPX1SuaLcGmVTF5q2tf8z
17 +a3qwCqJxuChHWfL5C0F/iq24OYEPEFQAKqWqSJXk8Y5icuu8ZyPEaEjBJqCxoWdn
18 +bfc4OHwfSxvpg3AbaCuB9DsjF0zUmYZYSAPSduMOrDUo2fC2AI3A0UgjJex0pD0q
19 +ricy3QCWIzVPdWYThthWwuMnND7oiqhOrweZlH2FiSodkvbyFkENQFRjvDmWoM7J
20 +93ryfbcDOJfnBEA07S/3ljwFBwzNs5pw4h8LzRRNHg1tXk1Eu4kecGHmiW5bej4H
21 +l4/nnfqOSyRtOoLaAQ==
22 +-----END CERTIFICATE-----
1 +RSA Private-Key: (2048 bit, 2 primes)
2 +modulus:
3 + 00:d1:e1:02:37:fc:1c:07:dd:cb:4b:f5:e6:d7:97:
4 + d4:43:4a:dd:e6:8b:17:5e:06:8a:0b:8e:73:9f:ca:
5 + 99:a0:18:62:3d:67:22:5e:cb:19:d8:e2:ba:60:7a:
6 + 54:94:f4:7a:54:48:03:1d:43:08:6a:0f:0c:df:1d:
7 + e4:38:5f:ae:97:ed:6e:5b:fb:94:f1:54:39:52:a9:
8 + 23:a4:63:72:5e:84:55:10:8e:9b:72:3a:4d:e8:57:
9 + 6b:38:3d:00:27:47:44:0f:fc:bb:12:c6:f0:c1:4a:
10 + b2:60:15:87:5c:10:5c:69:c1:56:8a:1b:81:9c:8d:
11 + 0e:ad:f2:53:87:74:cb:aa:5a:0a:f1:c2:55:50:53:
12 + 20:1f:cc:76:29:29:bc:b8:83:45:fa:c1:f6:6e:8b:
13 + e5:80:ba:02:ec:7a:0e:7d:a7:7d:7f:86:4d:4b:f1:
14 + 5f:39:2c:e1:1a:03:b4:90:22:92:59:df:73:38:05:
15 + 0d:57:3c:a0:de:99:32:99:6a:03:84:cf:17:ae:d3:
16 + 2e:c6:34:ef:5c:76:5d:02:29:52:bb:96:95:e5:a8:
17 + e0:c7:59:3c:84:2b:fd:ec:76:58:5b:db:25:3f:3e:
18 + 63:ac:2c:11:f0:f6:02:00:b1:04:1b:93:85:56:21:
19 + 9a:c1:5a:01:fd:1f:62:ff:9f:b5:0c:1d:eb:4a:01:
20 + 76:83
21 +publicExponent: 65537 (0x10001)
22 +privateExponent:
23 + 58:e9:ad:fa:f1:bf:1e:46:03:fe:26:2a:a9:63:14:
24 + f5:7d:1e:0c:b1:18:31:29:2c:0a:41:4b:12:82:ce:
25 + 1a:58:ba:25:b1:2f:8a:61:18:8e:1d:5f:3f:c8:13:
26 + 55:17:4d:4b:af:46:42:7b:47:71:46:f6:f8:fe:bc:
27 + d4:75:14:8e:20:74:04:5b:cc:79:80:68:d8:6f:f7:
28 + 3d:89:33:c6:7e:e1:5a:a6:4f:8c:50:ce:f8:83:30:
29 + 55:1e:e2:95:c1:47:40:4e:9d:22:13:4d:a3:55:75:
30 + c3:e6:da:f5:51:a9:14:d4:67:49:12:e6:11:e0:60:
31 + 3b:a8:d1:62:2d:44:aa:e1:bd:db:44:de:61:aa:41:
32 + a0:24:92:e7:2f:ec:59:34:7a:13:d5:5e:4e:b8:14:
33 + 66:26:2f:31:42:1b:61:46:ef:a6:c5:31:9c:65:f6:
34 + 35:a8:76:ef:fd:12:d1:1f:7d:cc:62:34:5b:42:47:
35 + fa:33:58:46:58:80:23:63:48:36:70:4b:e9:a4:88:
36 + 81:c2:33:d9:6a:49:a8:b8:ce:7f:ea:09:82:6b:78:
37 + ac:4f:59:9d:d0:37:59:38:03:14:38:94:c0:2f:23:
38 + de:ab:c4:90:2e:9c:95:3c:e0:f0:8b:d2:16:40:7f:
39 + 01:39:5a:fa:c7:68:09:ab:60:b0:f0:b9:3b:1b:08:
40 + 21
41 +prime1:
42 + 00:f4:8c:0f:79:cc:a7:df:76:72:7a:f9:05:02:47:
43 + 95:e7:7b:ad:9f:ae:45:ac:f1:81:d1:5c:eb:38:c5:
44 + fc:90:ce:79:0a:9c:c2:bd:4f:08:ef:3a:46:e9:4d:
45 + 22:29:93:50:3d:54:98:a8:74:ca:f5:c7:4b:60:7d:
46 + d3:b7:c8:ca:f3:d6:14:8b:45:9f:04:7f:71:03:3f:
47 + 30:f3:2d:fb:bd:83:81:22:d6:9a:3d:cd:f2:8e:d5:
48 + 0a:6e:17:a4:2c:62:46:da:4a:f6:d9:98:cf:1d:67:
49 + 72:45:dd:70:4f:0c:69:11:9c:a0:25:26:25:a4:59:
50 + b3:ea:6e:39:7e:4c:a6:b1:cf
51 +prime2:
52 + 00:db:b5:4d:6a:7b:ce:a1:16:2b:bd:56:b2:3f:fb:
53 + 43:dd:5e:5e:b5:f1:86:eb:ad:1b:73:2d:f4:96:52:
54 + 8d:4c:ae:34:3d:d6:8a:1d:07:fd:8b:7c:0b:66:b3:
55 + 49:72:37:f8:f1:f9:7d:d8:b0:c5:12:c0:66:f3:99:
56 + 10:e5:71:a8:22:47:9b:d6:bf:5f:05:91:d5:c7:f0:
57 + 2a:48:3c:a4:ae:00:5f:09:70:c3:a9:48:1d:22:6f:
58 + d5:94:83:52:cf:2d:d9:cf:1b:80:f2:4e:2a:18:3c:
59 + 36:e7:6d:57:01:e5:60:8f:52:e6:3a:ec:dc:94:ec:
60 + a1:3b:07:f3:e5:72:e5:61:0d
61 +exponent1:
62 + 00:e8:f9:d6:74:8f:49:0f:57:64:d1:4b:14:3e:8b:
63 + bc:80:80:0f:75:25:2e:34:09:11:48:48:61:c0:00:
64 + bf:11:a5:e3:22:fd:1d:7a:05:25:d9:e3:87:53:14:
65 + ad:0b:36:d1:26:dc:c5:63:17:81:94:8d:7d:7e:3b:
66 + e1:cc:21:7b:58:ba:07:70:77:af:7b:35:7e:91:3d:
67 + 4e:81:1e:b9:ca:5e:d2:54:42:67:47:a2:41:07:5a:
68 + 67:49:63:34:81:24:4f:a3:ff:ef:14:76:c4:3a:9b:
69 + 26:fe:f0:6b:e2:a3:4c:25:ff:35:82:ae:c9:05:be:
70 + 7f:ed:43:7d:7a:99:c3:e5:79
71 +exponent2:
72 + 00:b7:52:28:dd:4f:9e:92:84:68:4c:9c:79:30:af:
73 + 9b:e9:aa:a3:46:16:d8:67:ef:51:b7:22:42:31:e7:
74 + 81:a4:d8:ba:18:5a:d9:74:ed:c4:dd:cc:cb:ca:8e:
75 + 90:1a:f0:9f:14:70:03:54:79:f2:85:f9:ea:2d:19:
76 + ab:a2:76:da:3e:78:17:8c:f0:b2:fd:77:b8:b4:12:
77 + 2d:85:86:ac:35:cf:73:7c:f2:0d:20:43:5e:a3:ec:
78 + 42:7e:9f:b0:c9:d3:cd:28:65:1f:8b:8e:32:cb:73:
79 + fa:af:d1:68:c6:d9:38:5f:7e:61:42:0b:7e:e5:f8:
80 + 27:73:94:e8:29:ac:5b:be:45
81 +coefficient:
82 + 19:e9:84:ba:58:9b:8f:dc:52:4b:03:3f:9b:65:cc:
83 + d7:6a:04:9a:2c:66:40:2d:cf:2e:90:32:52:44:f6:
84 + 21:74:65:dc:6a:27:8d:23:79:09:ea:53:45:39:e4:
85 + 40:e7:d2:d0:1c:aa:1a:68:fe:56:69:2b:3b:55:20:
86 + ff:0b:84:b0:c4:af:ed:33:dd:c4:fe:5c:10:5d:b9:
87 + 5b:6d:b2:bd:2f:e9:03:8f:29:5e:38:17:a3:2c:14:
88 + 6c:08:cb:cb:10:5c:9e:c6:cb:c4:9f:99:6e:76:96:
89 + 2a:0a:19:cf:33:f3:d0:ba:b0:d6:77:0d:71:1f:3f:
90 + 5c:95:ff:9e:61:ce:ab:49
91 +-----BEGIN RSA PRIVATE KEY-----
92 +MIIEpAIBAAKCAQEA0eECN/wcB93LS/Xm15fUQ0rd5osXXgaKC45zn8qZoBhiPWci
93 +XssZ2OK6YHpUlPR6VEgDHUMIag8M3x3kOF+ul+1uW/uU8VQ5UqkjpGNyXoRVEI6b
94 +cjpN6FdrOD0AJ0dED/y7EsbwwUqyYBWHXBBcacFWihuBnI0OrfJTh3TLqloK8cJV
95 +UFMgH8x2KSm8uINF+sH2bovlgLoC7HoOfad9f4ZNS/FfOSzhGgO0kCKSWd9zOAUN
96 +Vzyg3pkymWoDhM8XrtMuxjTvXHZdAilSu5aV5ajgx1k8hCv97HZYW9slPz5jrCwR
97 +8PYCALEEG5OFViGawVoB/R9i/5+1DB3rSgF2gwIDAQABAoIBAFjprfrxvx5GA/4m
98 +KqljFPV9HgyxGDEpLApBSxKCzhpYuiWxL4phGI4dXz/IE1UXTUuvRkJ7R3FG9vj+
99 +vNR1FI4gdARbzHmAaNhv9z2JM8Z+4VqmT4xQzviDMFUe4pXBR0BOnSITTaNVdcPm
100 +2vVRqRTUZ0kS5hHgYDuo0WItRKrhvdtE3mGqQaAkkucv7Fk0ehPVXk64FGYmLzFC
101 +G2FG76bFMZxl9jWodu/9EtEffcxiNFtCR/ozWEZYgCNjSDZwS+mkiIHCM9lqSai4
102 +zn/qCYJreKxPWZ3QN1k4AxQ4lMAvI96rxJAunJU84PCL0hZAfwE5WvrHaAmrYLDw
103 +uTsbCCECgYEA9IwPecyn33ZyevkFAkeV53utn65FrPGB0VzrOMX8kM55CpzCvU8I
104 +7zpG6U0iKZNQPVSYqHTK9cdLYH3Tt8jK89YUi0WfBH9xAz8w8y37vYOBItaaPc3y
105 +jtUKbhekLGJG2kr22ZjPHWdyRd1wTwxpEZygJSYlpFmz6m45fkymsc8CgYEA27VN
106 +anvOoRYrvVayP/tD3V5etfGG660bcy30llKNTK40PdaKHQf9i3wLZrNJcjf48fl9
107 +2LDFEsBm85kQ5XGoIkeb1r9fBZHVx/AqSDykrgBfCXDDqUgdIm/VlINSzy3ZzxuA
108 +8k4qGDw2521XAeVgj1LmOuzclOyhOwfz5XLlYQ0CgYEA6PnWdI9JD1dk0UsUPou8
109 +gIAPdSUuNAkRSEhhwAC/EaXjIv0degUl2eOHUxStCzbRJtzFYxeBlI19fjvhzCF7
110 +WLoHcHevezV+kT1OgR65yl7SVEJnR6JBB1pnSWM0gSRPo//vFHbEOpsm/vBr4qNM
111 +Jf81gq7JBb5/7UN9epnD5XkCgYEAt1Io3U+ekoRoTJx5MK+b6aqjRhbYZ+9RtyJC
112 +MeeBpNi6GFrZdO3E3czLyo6QGvCfFHADVHnyhfnqLRmronbaPngXjPCy/Xe4tBIt
113 +hYasNc9zfPINIENeo+xCfp+wydPNKGUfi44yy3P6r9Foxtk4X35hQgt+5fgnc5To
114 +KaxbvkUCgYAZ6YS6WJuP3FJLAz+bZczXagSaLGZALc8ukDJSRPYhdGXcaieNI3kJ
115 +6lNFOeRA59LQHKoaaP5WaSs7VSD/C4SwxK/tM93E/lwQXblbbbK9L+kDjyleOBej
116 +LBRsCMvLEFyexsvEn5ludpYqChnPM/PQurDWdw1xHz9clf+eYc6rSQ==
117 +-----END RSA PRIVATE KEY-----
This diff could not be displayed because it is too large.
1 +{
2 + "name": "likeback",
3 + "version": "1.0.0",
4 + "description": "",
5 + "main": "index.js",
6 + "scripts": {
7 + "test": "echo \"Error: no test specified\" && exit 1",
8 + "start": "node src",
9 + "start:dev": "nodemon --watch src/ src/index.js"
10 + },
11 + "author": "",
12 + "license": "ISC",
13 + "dependencies": {
14 + "@hapi/joi": "^17.1.1",
15 + "@koa/router": "^10.1.1",
16 + "bcrypt": "^5.0.1",
17 + "crypto": "^1.0.1",
18 + "dotenv": "^10.0.0",
19 + "express": "^4.17.1",
20 + "firebase": "^9.6.0",
21 + "http2": "^3.3.7",
22 + "jsonwebtoken": "^8.5.1",
23 + "koa": "^2.13.4",
24 + "koa-body": "^4.2.0",
25 + "koa-bodyparser": "^4.3.0",
26 + "koa-router": "^10.1.1",
27 + "koa-send": "^5.0.1",
28 + "mongoose": "^6.0.12",
29 + "nodemailer": "^6.7.1",
30 + "passport": "^0.5.0",
31 + "passport-google-oauth": "^2.0.0",
32 + "spdy": "^4.0.2"
33 + },
34 + "devDependencies": {
35 + "eslint": "^8.2.0"
36 + }
37 +}
1 +-----BEGIN CERTIFICATE-----
2 +MIIDmTCCAoECFA0G8CsoOzEJaSus1d0/oC6+WzOcMA0GCSqGSIb3DQEBCwUAMIGI
3 +MQswCQYDVQQGEwJLcjEOMAwGA1UECAwFU2VvdWwxETAPBgNVBAcMCEd3YW5ha0d1
4 +MQswCQYDVQQKDAJUdzERMA8GA1UECwwIVHdTaXN0ZXIxETAPBgNVBAMMCGxpa2Uu
5 +Y29tMSMwIQYJKoZIhvcNAQkBFhR5b29iaW5wYXJrQGtodS5hYy5rcjAeFw0yMTEx
6 +MTAwNTAzNDhaFw0zMTExMDgwNTAzNDhaMIGIMQswCQYDVQQGEwJLcjEOMAwGA1UE
7 +CAwFU2VvdWwxETAPBgNVBAcMCEd3YW5ha0d1MQswCQYDVQQKDAJUdzERMA8GA1UE
8 +CwwIVHdTaXN0ZXIxETAPBgNVBAMMCGxpa2UuY29tMSMwIQYJKoZIhvcNAQkBFhR5
9 +b29iaW5wYXJrQGtodS5hYy5rcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
10 +ggEBANHhAjf8HAfdy0v15teX1ENK3eaLF14GiguOc5/KmaAYYj1nIl7LGdjiumB6
11 +VJT0elRIAx1DCGoPDN8d5Dhfrpftblv7lPFUOVKpI6Rjcl6EVRCOm3I6TehXazg9
12 +ACdHRA/8uxLG8MFKsmAVh1wQXGnBVoobgZyNDq3yU4d0y6paCvHCVVBTIB/Mdikp
13 +vLiDRfrB9m6L5YC6Aux6Dn2nfX+GTUvxXzks4RoDtJAiklnfczgFDVc8oN6ZMplq
14 +A4TPF67TLsY071x2XQIpUruWleWo4MdZPIQr/ex2WFvbJT8+Y6wsEfD2AgCxBBuT
15 +hVYhmsFaAf0fYv+ftQwd60oBdoMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAPIuB
16 +rauwsJoEQvMH6G4b7AXyyKytfmOkK3e8RSvNeeu/IUoAPX1SuaLcGmVTF5q2tf8z
17 +a3qwCqJxuChHWfL5C0F/iq24OYEPEFQAKqWqSJXk8Y5icuu8ZyPEaEjBJqCxoWdn
18 +bfc4OHwfSxvpg3AbaCuB9DsjF0zUmYZYSAPSduMOrDUo2fC2AI3A0UgjJex0pD0q
19 +ricy3QCWIzVPdWYThthWwuMnND7oiqhOrweZlH2FiSodkvbyFkENQFRjvDmWoM7J
20 +93ryfbcDOJfnBEA07S/3ljwFBwzNs5pw4h8LzRRNHg1tXk1Eu4kecGHmiW5bej4H
21 +l4/nnfqOSyRtOoLaAQ==
22 +-----END CERTIFICATE-----
1 +-----BEGIN CERTIFICATE REQUEST-----
2 +MIICzjCCAbYCAQAwgYgxCzAJBgNVBAYTAktyMQ4wDAYDVQQIDAVTZW91bDERMA8G
3 +A1UEBwwIR3dhbmFrR3UxCzAJBgNVBAoMAlR3MREwDwYDVQQLDAhUd1Npc3RlcjER
4 +MA8GA1UEAwwIbGlrZS5jb20xIzAhBgkqhkiG9w0BCQEWFHlvb2JpbnBhcmtAa2h1
5 +LmFjLmtyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0eECN/wcB93L
6 +S/Xm15fUQ0rd5osXXgaKC45zn8qZoBhiPWciXssZ2OK6YHpUlPR6VEgDHUMIag8M
7 +3x3kOF+ul+1uW/uU8VQ5UqkjpGNyXoRVEI6bcjpN6FdrOD0AJ0dED/y7EsbwwUqy
8 +YBWHXBBcacFWihuBnI0OrfJTh3TLqloK8cJVUFMgH8x2KSm8uINF+sH2bovlgLoC
9 +7HoOfad9f4ZNS/FfOSzhGgO0kCKSWd9zOAUNVzyg3pkymWoDhM8XrtMuxjTvXHZd
10 +AilSu5aV5ajgx1k8hCv97HZYW9slPz5jrCwR8PYCALEEG5OFViGawVoB/R9i/5+1
11 +DB3rSgF2gwIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBACC2EZvLB/YvSLHgDVoE
12 +QDefpbCLJ2Dm8/CeRrGPKpJK4ozGFNox026SM+UH0zU3V3kLqu41uN7Jgofc3XTU
13 +cpmTeMRmFgd8+csXwM1evuFJUNfcwQTxNDlbn9IOsdn7TXF5uhjt4+nAZ0SvRSGg
14 +59VsZEXUNnbevFN87ihd8AVjTGz0nuYLIxJ51s98ND32R0/UaofZqu4niH6FcKNR
15 +U9NlHPTL1/XPqC+qSBlPVlADeUEBobEXzFo4yzPlv4JLFWV0gVOGYLtoK5m+Q2WS
16 +xbhL+c+S8Dz87aJ2wlj8lDYbRsUqu+GCNjcOqAmSnZPkq1UoObzV01pXMtqL2jry
17 +ebw=
18 +-----END CERTIFICATE REQUEST-----
1 +-----BEGIN RSA PRIVATE KEY-----
2 +MIIEpAIBAAKCAQEA0eECN/wcB93LS/Xm15fUQ0rd5osXXgaKC45zn8qZoBhiPWci
3 +XssZ2OK6YHpUlPR6VEgDHUMIag8M3x3kOF+ul+1uW/uU8VQ5UqkjpGNyXoRVEI6b
4 +cjpN6FdrOD0AJ0dED/y7EsbwwUqyYBWHXBBcacFWihuBnI0OrfJTh3TLqloK8cJV
5 +UFMgH8x2KSm8uINF+sH2bovlgLoC7HoOfad9f4ZNS/FfOSzhGgO0kCKSWd9zOAUN
6 +Vzyg3pkymWoDhM8XrtMuxjTvXHZdAilSu5aV5ajgx1k8hCv97HZYW9slPz5jrCwR
7 +8PYCALEEG5OFViGawVoB/R9i/5+1DB3rSgF2gwIDAQABAoIBAFjprfrxvx5GA/4m
8 +KqljFPV9HgyxGDEpLApBSxKCzhpYuiWxL4phGI4dXz/IE1UXTUuvRkJ7R3FG9vj+
9 +vNR1FI4gdARbzHmAaNhv9z2JM8Z+4VqmT4xQzviDMFUe4pXBR0BOnSITTaNVdcPm
10 +2vVRqRTUZ0kS5hHgYDuo0WItRKrhvdtE3mGqQaAkkucv7Fk0ehPVXk64FGYmLzFC
11 +G2FG76bFMZxl9jWodu/9EtEffcxiNFtCR/ozWEZYgCNjSDZwS+mkiIHCM9lqSai4
12 +zn/qCYJreKxPWZ3QN1k4AxQ4lMAvI96rxJAunJU84PCL0hZAfwE5WvrHaAmrYLDw
13 +uTsbCCECgYEA9IwPecyn33ZyevkFAkeV53utn65FrPGB0VzrOMX8kM55CpzCvU8I
14 +7zpG6U0iKZNQPVSYqHTK9cdLYH3Tt8jK89YUi0WfBH9xAz8w8y37vYOBItaaPc3y
15 +jtUKbhekLGJG2kr22ZjPHWdyRd1wTwxpEZygJSYlpFmz6m45fkymsc8CgYEA27VN
16 +anvOoRYrvVayP/tD3V5etfGG660bcy30llKNTK40PdaKHQf9i3wLZrNJcjf48fl9
17 +2LDFEsBm85kQ5XGoIkeb1r9fBZHVx/AqSDykrgBfCXDDqUgdIm/VlINSzy3ZzxuA
18 +8k4qGDw2521XAeVgj1LmOuzclOyhOwfz5XLlYQ0CgYEA6PnWdI9JD1dk0UsUPou8
19 +gIAPdSUuNAkRSEhhwAC/EaXjIv0degUl2eOHUxStCzbRJtzFYxeBlI19fjvhzCF7
20 +WLoHcHevezV+kT1OgR65yl7SVEJnR6JBB1pnSWM0gSRPo//vFHbEOpsm/vBr4qNM
21 +Jf81gq7JBb5/7UN9epnD5XkCgYEAt1Io3U+ekoRoTJx5MK+b6aqjRhbYZ+9RtyJC
22 +MeeBpNi6GFrZdO3E3czLyo6QGvCfFHADVHnyhfnqLRmronbaPngXjPCy/Xe4tBIt
23 +hYasNc9zfPINIENeo+xCfp+wydPNKGUfi44yy3P6r9Foxtk4X35hQgt+5fgnc5To
24 +KaxbvkUCgYAZ6YS6WJuP3FJLAz+bZczXagSaLGZALc8ukDJSRPYhdGXcaieNI3kJ
25 +6lNFOeRA59LQHKoaaP5WaSs7VSD/C4SwxK/tM93E/lwQXblbbbK9L+kDjyleOBej
26 +LBRsCMvLEFyexsvEn5ludpYqChnPM/PQurDWdw1xHz9clf+eYc6rSQ==
27 +-----END RSA PRIVATE KEY-----
1 +-----BEGIN RSA PRIVATE KEY-----
2 +Proc-Type: 4,ENCRYPTED
3 +DEK-Info: DES-EDE3-CBC,25A9EC1BE53CDC74
4 +
5 +FQR3tdxyJp2QHgJv+IqGVa3yAbOtR7J0AoLccoWmEMRN8Ch8Iso3RkKDpXo7Awa7
6 +EjnsIqTHqJl8AyD9DlkBRNnFog0mfnJJ1rHUyU9fOL+I2/B8R6qYFjvDpnTiC6Cp
7 +9Dz+Wn2KdhgkkoufvLEBW/BiiD2ScB/zk1POPXAWEBI8wQYSPsdWrxw8PtNbExt+
8 +9LApwYsDKpQnNAuYjiD/kZp9mz3qKO/kHS9R8nX8ZJq1c7D/SyN0in276T+OPk9C
9 +11Tcw86p+aoMVT2sU9CJ9N7rkFaOg1w1Hl27d4R6jvDDaYuvbsp41SKNJJbpnAQS
10 ++GtruJMjED8SOb4Sy4dRzZ6pZV/zPr/X7GcyANPC1RlxGjoWqLTuzruv4BSXf2Qk
11 +vLQF67FqpVBwIMY6GmzMrWeGfiK3i3WsqtMvCAPNPSO1d6EWzGNK5n68rBGk4fKF
12 +20gBWiab2f4osY4N7hPrDRRROVVlVFj9VUppQunyPYu5VEwAW+IQrb537QJp77ww
13 +ppAYoOjaiJHHPvnXP8JFCLSK1t8AeXl2GcrP5NEzCq8sMUXbClgd+gVynrqhN68I
14 +F7EOAYrvELapcURwu6Rnfxk9v8BTQoOt1hvcdLVcPah5+pkeGXy6JoHusDH+/3O7
15 +fi92tTPB2astbdPottuJuCHeyNaGRlFO+f81iePT91389jBDNFUNacERUwlQIZzd
16 +d8MXwHFlf4kUxlu6PXl8JeAXKHXrL9q3HAzeOZu+sJBt8cscQ/FVMjx4svYPCndl
17 +WGgb7Be052e1R/dOclfTKC6C24/6ek/UsPRIFem5BzP8lLocSDEp8Z55j3pGgyt0
18 +OAAuaVYwPVj56pXFoTWWModyux7YhBmqAl8Gguv53w5SyKviSPs0SoSWSQ3RaZig
19 +1f+rC1yBm2/kVV4Upbc2Jd5FGMjkUOPSbPKnk4yyZNEaIpuDkwjWdp9JU3DF2Zuh
20 +o+ZUkLZwmYYNFLB7ODwkekS4xE3M/YD4Dxn9D2VvZ7CUUP4FxqU3qPsdpzSgG9p9
21 +4FBmvmBxl6nMRLaOKwWeyj8SOtmm3x+OUs+meHL0T417CDQqv+wy7F9ikmxvo8/H
22 +XdRaKLemziI9R4NLJvmoFVJbrAP2CDM2DiiuMPcWv3WHBVSPU2s0fnNG75tS4iHl
23 +ZD/gCvL8jDMRml/r4kbwogg7YK/Ac6mmf5WqWK+t4QwDg6YwsKt5MDq8rf/7W5Lf
24 +TemIi8uoriE75XpCoMTqNWbdVUolos4n09B1l5Xx14fiOo9HGrhz7CgEpalNidqM
25 +0X3OLeZm/wdoJ3rusPRv5r/giObMRvOc9qN3RJpKYcEK99xHLVAPV6V6DASWMnCs
26 +Iknz4cBOdpR+WDcEUUi9aFkRuc9mw/iI/JMY5MDZzbWod2hF7VZ2Yko6JTuW9Y8R
27 +Jk0HgoI0YZdrnD6b/EmLdJcsZIIg6H4wBg56KTuP/jxOGgvcD03tPnyCOGaXOdCH
28 +c1kKo8N55Q0oFfdrVlBriptZeiqdFZ52vhThDR0z1DIeVuOiDeALvYdEhzR8oTJC
29 +ZKtqaQsUQiMVn4ZHiKex+9+OWhkArXoPYcyGuaT7coM5rWiwwbqP89tgPMUaIbbo
30 +-----END RSA PRIVATE KEY-----
1 +const Joi = require('@hapi/joi');
2 +const User = require('../../models/user');
3 +const Book = require('../../models/book');
4 +const Page = require('../../models/page');
5 +const nodemailer = require('nodemailer');
6 +const config = require('../../lib/config');
7 +const { Mongoose } = require('mongoose');
8 +const { exist, allow } = require('@hapi/joi');
9 +const fs = require('fs');
10 +exports.test = async (ctx) => {
11 + console.log('cookie');
12 + ctx.cookies.set('second', 22222, {
13 + httpOnly: false
14 + })
15 + ctx.body = {code: 200, message: 'success'}
16 +};
17 +
18 +exports.signupLocal = async (ctx) => {
19 + const { email, password, address } = ctx.request.body;
20 + console.log(ctx.request.body);
21 + const schema = Joi.object().keys({
22 + email: Joi.string().min(3).required(),
23 + password: Joi.string().required(),
24 + phone: Joi.string().allow(null, ''),
25 + nickname:Joi.string().allow(null, '')
26 + });
27 +
28 + //검증 결과
29 + try {
30 + const value = await schema.validateAsync(ctx.request.body);
31 + } catch (err) {
32 + console.log(err);
33 + ctx.status = 400;
34 + return;
35 + }
36 +
37 + try {
38 + // email 이미 존재하는지 확인
39 + const exists = await User.findByEmail(email);
40 + if (exists) {
41 + ctx.status = 409; // Conflict
42 + return;
43 + }
44 +
45 + let account = null;
46 + try {
47 + account = await User.localRegister(ctx.request.body);
48 + } catch (e) {
49 + ctx.throw(500, e);
50 + }
51 +
52 + let token = null;
53 + try {
54 + token = await account.generateToken();
55 + console.log('token ok');
56 + } catch (e) {
57 + ctx.throw(500, e);
58 + }
59 + ctx.cookies.set('access_token', token, { maxAge: 1000 * 60 * 60 * 24 * 7 ,httpOnly: true,});
60 + console.log('set cookie ok');
61 +
62 + // 응답할 데이터에서 hashedPassword 필드 제거
63 + ctx.status = 200;
64 + ctx.body = await account.serialize();
65 + } catch (e) {
66 + ctx.throw(500, e);
67 + }
68 +};
69 +exports.signinLocal = async (ctx) => {
70 + // 로그인
71 + const { email, password } = ctx.request.body;
72 +
73 + //handle error
74 + if (!email || !password) {
75 + ctx.status = 401; //Unauthorized
76 + return;
77 + }
78 + try {
79 + const user = await User.findOne({ email: email });
80 + //const user = await User.findByEmail(email);
81 + //계정없으면 에러처리
82 + console.log(user);
83 + if (!user) {
84 + ctx.status = 401;
85 + return;
86 + }
87 +
88 + const valid = await user.checkPassword(password);
89 + if (!valid) {
90 + ctx.status = 401;
91 + return;
92 + }
93 + ctx.body = await user.serialize();
94 + const token = user.generateToken();
95 + ctx.cookies.set('access_token', token, {
96 + maxAge: 1000 * 60 * 60 * 24 * 7, // 7일
97 + httpOnly: false,
98 + });
99 + ctx.status = 200;
100 + console.log('토큰나옴');
101 + } catch (e) {
102 + ctx.throw(500, e);
103 + }
104 +};
105 +
106 +
107 +/*
108 +exports.localLogin = async (ctx) => {
109 + // 데이터 검증
110 + const schema = Joi.object().keys({
111 + email: Joi.string().email().required(),
112 + password: Joi.string().required()
113 + });
114 +
115 + const result = Joi.validate(ctx.request.body, schema);
116 +
117 + if (result.error) {
118 + ctx.status = 400; // Bad Request
119 + return;
120 + }
121 +
122 + const { email, password } = ctx.request.body;
123 +
124 + let account = null;
125 + try {
126 + // 이메일로 계정 찾기
127 + account = await User.findByEmail(email);
128 + }
129 + catch (e) {
130 + ctx.throw(500, e);
131 + }
132 +
133 + if (!account || !account.checkPassword(password)) {
134 + // 유저가 존재하지 않거나 || 비밀번호가 일치하지 않으면
135 + ctx.status = 403; // Forbidden
136 + return;
137 + }
138 +
139 + let token = null;
140 + try {
141 + token = await account.generateToken();
142 + } catch (e) {
143 + ctx.throw(500, e);
144 + }
145 +
146 + ctx.cookies.set('access_token', token, { httpOnly: true, maxAge: 1000 * 60 * 60 * 24 * 7 });
147 + ctx.body = account.email;
148 +};*/
149 +exports.userlist = async (ctx) => {
150 + let user;
151 +
152 + try {
153 + user = await User.find()
154 + .sort({created: -1})
155 + .exec();
156 + } catch (e) {
157 + return ctx.throw(500, e);
158 + }
159 +
160 + ctx.body = user;
161 +}
162 +
163 +exports.exists = async (ctx) => {
164 + const { email } = ctx.request.body;
165 +
166 + try {
167 + const exists = await User.findByEmail(email);
168 + if (exists) {
169 + ctx.status = 409;
170 + return;
171 + }
172 + ctx.status = 200;
173 + } catch (e) {
174 + ctx.throw(500, e);
175 + }
176 +};
177 +
178 +exports.checkPassword = async (ctx) => {
179 + const { email, password } = ctx.request.body;
180 +
181 + try {
182 + const user = await User.findOne({ email: email });
183 + const valid = await user.checkPassword(password);
184 + if (valid) {
185 + ctx.status = 200;
186 + console.log("Check password success");
187 + return;
188 + } else if(!valid){
189 + ctx.status = 401;
190 + console.log("Check password fail");
191 + return;
192 + }
193 + } catch (e) {
194 + ctx.throw(500, e);
195 + }
196 +};
197 +//회원가입
198 +exports.signup = async (ctx) => {
199 + const { email, password, phone, fcmToken } = ctx.request.body;
200 + const schema = Joi.object().keys({
201 + email: Joi.string().min(3).required(),
202 + password: Joi.string().required().min(6),
203 + phone: Joi.string().allow(null, ''),
204 + fcmToken: Joi.string().allow(null, ''),
205 + nickname:Joi.string().allow(null, '')
206 + });
207 +
208 + let value= null;
209 + try {
210 + value = await schema.validateAsync(ctx.request.body);
211 + } catch (err) {
212 + console.log(err);
213 + ctx.status = 400;
214 + return;
215 + }
216 +
217 + try {
218 + // email 이미 존재하는지 확인
219 + const exists = await User.findByEmail(email);
220 + if (exists) {
221 + ctx.status = 409; // Conflict
222 + ctx.body = {
223 + key: exists.email === ctx.request.body.email ? 'email' : 'username'
224 + };
225 + return;
226 + }
227 + }catch(e)
228 + {
229 + ctx.throw(500, e);
230 + }
231 +
232 + let account = null;
233 + try {
234 + account = await User.localRegister(ctx.request.body);
235 + } catch (e) {
236 + ctx.throw(500, e);
237 + }
238 +
239 + let token = null;
240 + try {
241 + token = await account.generateToken();
242 + console.log('token ok');
243 + } catch (e) {
244 + ctx.throw(500, e);
245 + }
246 + ctx.cookies.set('access_token', token, { maxAge: 1000 * 60 * 60 * 24 * 7 ,httpOnly: true,});
247 + console.log('set cookie ok');
248 +
249 + // const user = new User(ctx.request.body);
250 + console.log(ctx.cookies);
251 + ctx.status = 200;
252 +};
253 +
254 +exports.signin = async (ctx) => {
255 + // 로그인
256 + const { email, password } = ctx.request.body;
257 +
258 + //handle error
259 + if (!email || !password) {
260 + ctx.status = 401; //Unauthorized
261 + return;
262 + }
263 + let user = null;
264 + try {
265 + user = await User.findOne({ email: email });
266 + //const user = await User.findByEmail(email);
267 + //계정없으면 에러처리
268 + if (!user) {
269 + ctx.status = 401;
270 + return;
271 + }
272 + } catch (e) {
273 + ctx.throw(500, e);
274 + }
275 + const valid = await user.checkPassword(password);
276 + if (!valid) {
277 + ctx.status = 401;
278 + return;
279 + }
280 + console.log(user);
281 + console.log('check password');
282 + let token = null;
283 + try{
284 + token = await user.generateToken();
285 + }catch (e) {
286 + ctx.throw(500, e);
287 + }
288 + ctx.cookies.set('access_token', token, {
289 + maxAge: 1000 * 60 * 60 * 24 * 7, // 7일
290 + httpOnly: true,
291 + });
292 + console.log('login cookie');
293 +
294 + ctx.status = 200;
295 + console.log('200');
296 +};
297 +
298 +exports.check = async (ctx) => {
299 + const { user } = ctx.state;
300 + if (!user) {
301 + ctx.status = 401;
302 + return;
303 + }
304 + ctx.body = user;
305 + // 로그인 상태 확인
306 +};
307 +exports.check2 = (ctx) => {
308 + const { user } = ctx.request;
309 +
310 + if(!user) {
311 + ctx.status = 403; // Forbidden
312 + return;
313 + }
314 +
315 + ctx.body = user.profile;
316 +};
317 +
318 +
319 +
320 +exports.signout = async (ctx) => {
321 + ctx.cookies.set('access_token');
322 + ctx.status = 204;
323 +};
324 +
325 +exports.Withdrawal = async (ctx) => {
326 + try {
327 + ctx.cookies.set('access_token');
328 + await Book. //delete pets owned by user
329 + User.deleteOne({ email: ctx.state.user.email }, function (err) {}); //delete user
330 + } catch (err) {
331 + ctx.throw(500, e);
332 + }
333 +
334 + ctx.status = 200;
335 +};
336 +
337 +exports.userinfo = async (ctx) => {
338 + const { _id } = ctx.state.user;
339 + try {
340 + const user = await User.findById(_id).exec();
341 + ctx.status = 200;
342 + ctx.body = await user.serialize();
343 + } catch (e) {
344 + ctx.throw(500, e);
345 + }
346 +};
347 +
348 +exports.updateUser = async (ctx) => {
349 + // 이메일 변경 불가
350 + // 비밀번호 변경은 따로
351 + //책과 게시글은 따로
352 + const schema = Joi.object().keys({
353 + // password: Joi.string().min(6).max(20).required(),
354 + username: Joi.string().allow(null, ''),
355 + phone: Joi.string().allow(null, ''),
356 + nickname: Joi.string().allow(null, ''),
357 + fcmToken: Joi.string(),
358 + // birth: Joi.date()
359 + });
360 +
361 + try {
362 + const value = await schema.validateAsync(ctx.request.body);
363 + } catch (err) {
364 + console.log(err);
365 + ctx.status = 400;
366 + return;
367 + }
368 +
369 + ctx.request.body.email = ctx.state.user.email;
370 +
371 + try {
372 + User.updateUser(ctx.request.body);
373 + } catch (e) {
374 + ctx.throw(500, e);
375 + }
376 + ctx.status = 200;
377 +};
378 +
379 +exports.changePassword = async (ctx) => {
380 + const schema = Joi.object().keys({
381 + email: Joi.string(),
382 + password: Joi.string().min(6).max(20).required(),
383 + });
384 +
385 + try {
386 + const value = await schema.validateAsync(ctx.request.body);
387 + } catch (err) {
388 + ctx.status = 400;
389 + return;
390 + }
391 + User.updatePassword(ctx.request.body.email, ctx.request.body.password);
392 + ctx.status = 200;
393 + ctx.body = { message: '비밀번호 변경 완료' };
394 +};
395 +
396 +exports.findPassword = async (ctx) => {
397 + var status = 400;
398 +
399 + // 전송 옵션 설정
400 + // trainsporter: is going to be an object that is able to send mail
401 + let transporter = nodemailer.createTransport({
402 + service: 'gmail',
403 + host: 'smtp.gmail.com',
404 + // port: 587,
405 + port: 465,
406 + secure: true,
407 + auth: {
408 + user: config.mailer.user, //gmail주소입력
409 + pass: config.mailer.password, //gmail패스워드 입력
410 + },
411 + });
412 +
413 + var mailOptions = {
414 + from: `"Like project"<${config.mailer.user}>`, //enter the send's name and email
415 + to: ctx.request.body.email, // recipient's email
416 + subject: 'Like password', // title of mail
417 + html: `안녕하세요, 글을 나누는 즐거움 Like 입니다.
418 + <br />
419 + 인증번호는 다음과 같습니다.
420 + <br />
421 + ${ctx.request.body.numsend}`,
422 + };
423 +
424 + try {
425 + await transporter.sendMail(mailOptions, async function (error, info) {
426 + if (error) {
427 + ctx.status = 401;
428 + return;
429 + } else {
430 + console.log('Email sent: ' + info.response);
431 + ctx.body = { success: true };
432 + status = 200;
433 + }
434 + });
435 + } catch (e) {
436 + ctx.throw(500, e);
437 + }
438 + ctx.status = 200;
439 +
440 +};
441 +
442 +//favorite(즐겨찾기)
443 +exports.addFavorite = async (ctx) => {
444 + id = ctx.request.body.contentsid;
445 + try {
446 + await User.updateFavorite(ctx.state.user.email, id);
447 + } catch (e) {
448 + console.log(e);
449 + }
450 +
451 + ctx.status = 200;
452 +};
453 +
454 +exports.delFavorite = async (ctx) => {
455 + try {
456 + await User.delFavorites(ctx.state.user.email, ctx.query.contentsid);
457 + } catch (e) {
458 + ctx.throw(500, e);
459 + }
460 + ctx.status = 200;
461 +};
462 +
463 +exports.showFavorite = async (ctx) => {
464 + try {
465 + const user = await User.findById(ctx.state.user._id).exec();
466 + //url, title, image
467 + const favbooks = await Book.find({_id:{$in:user.favorite}});
468 + ctx.status = 200;
469 + ctx.body = favbooks;
470 + } catch (e) {
471 + ctx.throw(500, e);
472 + }
473 +};
474 +
475 +
476 +exports.getUserBook = async (ctx) => {
477 + const user = await User.findById(ctx.state.user._id).exec();
478 + try {
479 + const mybook = await Book.find({_id:{$in:user.books}});
480 + ctx.body = mybook;
481 + } catch (e) {
482 + ctx.throw(500, e);
483 + }
484 + //const user = await User.findById(mybook.author).exec();
485 +
486 +
487 +};
...\ No newline at end of file ...\ No newline at end of file
1 +require('dotenv').config()
2 +const Router = require("@koa/router");
3 +const authCtrl = require("./auth.ctrl");
4 +const checkLoggedIn = require("../../lib/checkLoggedIn");
5 +var passport = require('passport');
6 +var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
7 +const auth = new Router();
8 +
9 +// 회원가입- 로컬 이메일 인증번호 발송 POST auth/signup/email/demand
10 +// 회원가입 이메일 인증번호 확인 POST auth/signup/email/verify
11 +// 로그인 "소셜 로그인
12 +// (페이스북 구글 네이버 카카오)" POST auth/signin/social
13 +// 회원정보갱신 설문이나 설정에서 개인정보 바꾸면 적용 PATCH auth/update/pet
14 +// 회원정보갱신 설문이나 설정에서 개인정보 바꾸면 적용 PATCH auth/update/user
15 +
16 +auth.get('/userlist', authCtrl.userlist);
17 +auth.get('/test', authCtrl.test);
18 +auth.post('/signup', authCtrl.signupLocal);
19 +auth.post('/signin', authCtrl.signinLocal);
20 +auth.get('/signout',checkLoggedIn, authCtrl.signout);
21 +auth.get('/check', authCtrl.check2);
22 +auth.delete('/user',checkLoggedIn,authCtrl.Withdrawal); // 회원 탈퇴
23 +auth.post('/validate', authCtrl.exists);
24 +auth.post('/checkpassword', authCtrl.checkPassword);
25 +auth.get('/book',checkLoggedIn,authCtrl.getUserBook);
26 +auth.get('/user', checkLoggedIn,authCtrl.userinfo); // show user information
27 +auth.patch('/user', checkLoggedIn, authCtrl.updateUser); // modify user information
28 +auth.patch('/user/password', authCtrl.changePassword); // change password
29 +
30 +auth.get('/favorite',checkLoggedIn, authCtrl.showFavorite); // show a list of user's favorites
31 +auth.post('/favorite',checkLoggedIn, authCtrl.addFavorite); // add favorite
32 +auth.delete('/favorite',checkLoggedIn, authCtrl.delFavorite); // delete favorite
33 +
34 +auth.post('/find/password', authCtrl.findPassword); // 비밀번호 찾기
35 +
36 +
37 +module.exports = auth;
...\ No newline at end of file ...\ No newline at end of file
1 +const Page = require("../../models/page");
2 +const User = require("../../models/user");
3 +const Book = require("../../models/book");
4 +const Joi = require('@hapi/joi');
5 +const config = require('../../lib/config');
6 +const { Mongoose } = require('mongoose');
7 +exports.booklist = async (ctx) => {
8 + let user;
9 +
10 + try {
11 + book = await Book.find()
12 + .sort({created: -1})
13 + .exec();
14 + } catch (e) {
15 + return ctx.throw(500, e);
16 + }
17 +
18 + ctx.body = book;
19 +}
20 +
21 +
22 +exports.addBook = async (ctx) => {
23 + //const file = ctx.request.files;
24 + // console.log("file\n", file)
25 + // console.log(file.image.path)
26 + //ctx.request.body.image = fs.readFileSync(file.image.path);
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 +
59 + });
60 + } catch (e) {
61 + ctx.throw(500, e);
62 + }
63 + ctx.body = book;
64 + ctx.status = 200;
65 +};
66 +
67 +exports.getOneBook = async (ctx) => {
68 +
69 + const bookid = ctx.request.body._id;
70 + console.log(bookid);
71 + try {
72 + const mybook = await Book.findById(bookid).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)
80 + //ctx.body.authorname = user.nickname;
81 + //ctx.body = mybook;
82 + } catch (e) {
83 + ctx.throw(500, e);
84 + }
85 + //const user = await User.findById(mybook.author).exec();
86 + //ctx.body = mybook;
87 +
88 +
89 +};
90 +
91 +
92 +
93 +exports.updateBook = async (ctx) => {
94 + // validation추가 필요
95 + const file = ctx.request.files;
96 + if(ctx.request.body.cover != undefined) // when user add a new pet image
97 + ctx.request.body.cover = fs.readFileSync(file.image.path);
98 + else
99 + ctx.request.body.cover = ""
100 +
101 + var book = ctx.request.body; //require books's _id
102 + try {
103 + const mybook = await Book.findOne({ _id: book._id });
104 +
105 + mybook.updateB(book);
106 +
107 + ctx.body = book._id;
108 + } catch (e) {
109 + ctx.throw(500, e);
110 + }
111 + ctx.body = book._id;
112 +
113 + console.log(book);
114 + ctx.status = 200;
115 + };
116 +
117 +
118 +exports.deleteBook = async (ctx) => {
119 + try {
120 + var b = await Book.find(ctx.params.id);
121 + await Page.deleteMany({"pages":{$in:b.pages}});//book에 있던 페이지 다 지우기
122 + } catch (e) {
123 + if(e.name === 'CastError') {
124 + ctx.status = 400;
125 + return;
126 + }
127 + }
128 + ctx.status = 204; // No Content
129 +};
130 +
131 +exports.detailBook = async (ctx) => {
132 + var ObjectId = require('mongodb').ObjectId;
133 + var id = req.params.book_id;
134 + var o_id = new ObjectId(id);
135 + const book = await db.Book.find({_id:o_id});
136 + ctx.body = book;
137 + ctx.status = 200;
138 +};
139 +
140 +exports.scrollBook = async (ctx) => {
141 + //클라이언트에서 미리 요청하는 방법 사용하자
142 +
143 + //select: 조회순 or 추천순
144 + //renewal: 앱 화면 바닥에 도달한 횟수 (처음으로 데이터를 추가로 가져올때 1, 그다음 2 ...)
145 + const {filter, renewal} = ctx.query
146 +
147 + if(filter === "조회순") { //조회순
148 + try {
149 + const books = await Book.find().sort({'views': -1}).skip(parseInt(renewal)*10).limit(10)
150 + let result = await bookInfo(books);
151 + ctx.status = 200;
152 + ctx.body = result;
153 + } catch (e) {
154 + ctx.throw(500, e);
155 + }
156 + }
157 +
158 + else if(filter === "추천순") { //추천순
159 +
160 + }
161 +};
1 +const Router = require("@koa/router");
2 +const checkLoggedIn = require("../../lib/checkLoggedIn");
3 +const bookCtrl = require("./book.ctrl");
4 +const book = new Router();
5 +
6 +book.get('/',bookCtrl.getOneBook);
7 +//mybook=page,title
8 +//author_name = author name
9 +book.post('/',checkLoggedIn,bookCtrl.addBook); // add book
10 +book.patch('/', checkLoggedIn, bookCtrl.updateBook); // modify book information
11 +book.delete('/',checkLoggedIn,bookCtrl.deleteBook); // delete book
12 +book.get('/booklist',bookCtrl.booklist);
13 +book.get('/search',bookCtrl.scrollBook);
14 +
15 +module.exports = book;
...\ No newline at end of file ...\ No newline at end of file
1 +
2 +const Router = require("koa-router");
3 +const Koa = require('koa');
4 +// Import the functions you need from the SDKs you need
5 +
6 +// TODO: Add SDKs for Firebase products that you want to use
7 +// https://firebase.google.com/docs/web/setup#available-libraries
8 +
9 +// Your web app's Firebase configuration
10 +const firebaseConfig = {
11 + apiKey: "AIzaSyDZw-VXcu0yP3m9r11fe3JiJ-_ksEQDX-E",
12 + authDomain: "like-c93bb.firebaseapp.com",
13 + projectId: "like-c93bb",
14 + storageBucket: "like-c93bb.appspot.com",
15 + messagingSenderId: "514516382912",
16 + appId: "1:514516382912:web:17460502317f4c51166925"
17 +};
18 +
19 +// Initialize Firebase
20 +
21 +firebase.initializeApp(firebaseConfig)
22 +let database = firebase.database();
23 +
24 +module.exports = database;
...\ No newline at end of file ...\ No newline at end of file
1 +const Router = require("koa-router");
2 +const page = require("./page");
3 +const auth = require("./auth");
4 +const book = require("./book");
5 +const api = new Router();
6 +
7 +api.use("/auth", auth.routes());
8 +api.use("/book", book.routes());
9 +api.use("/page", page.routes());
10 +
11 +api.get('/test', (ctx) => (ctx.body = 'hi'));
12 +module.exports = api;
13 +
1 +const Router = require("@koa/router");
2 +const checkLoggedIn = require("../../lib/checkLoggedIn");
3 +const pageCtrl = require("./page.ctrl");
4 +const page = new Router();
5 +
6 +//Page api
7 +page.get('/',pageCtrl.getPage); // show a list of user's pages
8 +page.post('/',checkLoggedIn,pageCtrl.addPage); // add page
9 +page.patch('/', checkLoggedIn,pageCtrl.updatePage); // modify page information
10 +page.delete('/',checkLoggedIn,pageCtrl.deletePage); // delete book
11 +
12 +page.get('/search', pageCtrl.search); // /search?title=search_query&petType=petType
13 +//page.post('/search/filter', pageCtrl.searchFilter); //아직 구현 안함
14 +page.post('/detail', pageCtrl.detailPage); // detail recipe page
15 +
16 +//page.get('/recipe/slide', pageCtrl.slidRecipe); // 5 recommended videos in main page
17 +
18 +// /recipe/scroll?filter=filter_query&renewal=count (filter_query: 추천순 or 조회순)
19 +page.get('/recipe/scroll', pageCtrl.scrollPage); // video list sorted by 추천순 or 조회순 in main page
20 +
21 +//page.post('/postinfo', pageCtrl.uploadInfo);
22 +//page.get('/info',pageCtrl.getbyurl);//url로 recipe정보 가져오기 (flutter 내 레시피에서 쓰임.)
23 +module.exports = page;
...\ No newline at end of file ...\ No newline at end of file
1 +const Page = require("../../models/page");
2 +const User = require("../../models/user");
3 +const Book = require("../../models/book");
4 +const Joi = require('@hapi/joi');
5 +const config = require('../../lib/config');
6 +const { Mongoose } = require('mongoose');
7 +exports.search = async (ctx) => {
8 + const { title } = ctx.query; //search word
9 + console.log(title)
10 + try {
11 + var pages = await Page.findBySearchWord(title);
12 + ctx.status = 200;
13 + ctx.body = pages;
14 + } catch (e) {
15 + ctx.throw(500, e);
16 + }
17 + ctx.status = 200;
18 +};
19 +
20 +
21 +exports.detailPage = async (ctx) => {
22 + var ObjectId = require('mongodb').ObjectId;
23 + var id = req.params.page_id;
24 + var o_id = new ObjectId(id);
25 + const page = await db.Page.find({_id:o_id});
26 + ctx.body = page;
27 + ctx.status = 200;
28 +};
29 +
30 +// parameters: array with book objects as elements
31 +// return image, title and author of book DB information
32 +//list에 보여질 정보 일부분
33 +async function bookInfo (arr) {
34 + let result = []
35 + arr.map(obj => {
36 + temp = new Object();
37 + temp.image = obj.image;
38 + temp.title = obj.title;
39 + temp.author = obj.author;
40 + temp.views = obj.views;
41 + result.push(temp);
42 + delete temp;
43 + })
44 + return result;
45 +}
46 +
47 +async function pageInfo (arr) {
48 + let result = []
49 + arr.map(obj => {
50 + temp = new Object();
51 + temp.image = obj.image;
52 + temp.title = obj.title;
53 + temp.author = obj.author;
54 + temp.views = obj.views;
55 + result.push(temp);
56 + delete temp;
57 + })
58 + return result;
59 +}
60 +
61 +
62 +
63 +
64 +exports.scrollPage = async (ctx) => {
65 + //클라이언트에서 미리 요청하는 방법 사용하자
66 +
67 + //select: 조회순 or 추천순
68 + //renewal: 앱 화면 바닥에 도달한 횟수 (처음으로 데이터를 추가로 가져올때 1, 그다음 2 ...)
69 + const {filter, renewal} = ctx.query
70 +
71 + if(filter === "조회순") { //조회순
72 + try {
73 + const pages = await Page.find().sort({'views': -1}).skip(parseInt(renewal)*10).limit(10)
74 + let result = await pageInfo(pages);
75 + ctx.status = 200;
76 + ctx.body = result;
77 + } catch (e) {
78 + ctx.throw(500, e);
79 + }
80 + }
81 +
82 + else if(filter === "추천순") { //추천순
83 +
84 + }
85 +};
86 +
87 +//pet
88 + exports.addPage = async (ctx) => {
89 + //const file = ctx.request.files;
90 + // console.log("file\n", file)
91 + // console.log(file.image.path)
92 + //ctx.request.body.image = fs.readFileSync(file.image.path);
93 + if( ctx.request.files==undefined)
94 + console.log("파일없음");
95 + else
96 + ctx.request.body.cover = ""
97 + const {
98 + title,
99 + author,
100 + contents,
101 + cover,
102 + hashtag,
103 + book,
104 + } = ctx.request.body;
105 +
106 + const schema = Joi.object().keys({
107 + title: Joi.string().required(),
108 + author: Joi.string(),
109 + contents: Joi.string().required(),
110 + hashtag: Joi.string().allow(null, ''),
111 + cover: Joi.allow(null, ''),
112 + book: Joi.string().allow(null, ''),
113 + });
114 +
115 +
116 + //검증 결과
117 + try {
118 + await schema.validateAsync(ctx.request.body);
119 + } catch (err) {
120 + console.log('add page validaton' + err);
121 + ctx.status = 400;
122 + return;
123 + }
124 + ctx.request.body.author = ctx.state.user;
125 + const page = new Page(ctx.request.body);
126 +
127 + try {
128 + page.save(async (err, page) => {
129 + if (err) throw err;
130 + const user = await User.findById(ctx.state.user._id).exec();
131 + if(page.book!='')
132 + {
133 + const result = await Book.findOneAndUpdate({_id: page.book}, {$push: {pages: page._id}});
134 + console.log(result);
135 + }
136 +
137 + });
138 + } catch (e) {
139 + ctx.throw(500, e);
140 + }
141 + ctx.body = page;
142 + ctx.status = 200;
143 + };
144 +
145 + exports.updatePage = async (ctx) => {
146 + // validation추가 필요
147 + if(ctx.request.files != undefined) // when user add a new pet image
148 + ctx.request.body.image = fs.readFileSync(file.image.path);
149 + else
150 + ctx.request.body.image = ""
151 +
152 + var user = ctx.request.body; //require user id
153 + try {
154 + const mybook = await Book.findOne({ _id: book._id });
155 +
156 + mybook.updateP(book);
157 +
158 + ctx.body = user._id;
159 + } catch (e) {
160 + ctx.throw(500, e);
161 + }
162 + ctx.body = user._id;
163 +
164 + console.log(user);
165 + ctx.status = 200;
166 + };
167 +
168 +
169 +exports.deletePage = async (ctx) => {
170 + try {
171 + var b = await Page.find(ctx.params.id);
172 + await Page.deleteMany({"pages":{$in:b.pages}});
173 + } catch (e) {
174 + if(e.name === 'CastError') {
175 + ctx.status = 400;
176 + return;
177 + }
178 + }
179 + ctx.status = 204; // No Content
180 +};
181 +
182 +exports.getPage = async (ctx) => {
183 + const pageid = ctx.request.body._id;
184 + try {
185 + const mypage = await Book.findById(pageid).exec();
186 + const user = await User.findById(mypage.author).exec();//작가정보
187 + const author_name = user.nickname;
188 + ctx.body = {mypage,author_name:author_name}
189 + console.log(mypage)
190 +
191 + } catch (e) {
192 + ctx.throw(500, e);
193 + }
194 +
195 +};
1 +const http2 = require('http2');
2 +var fs = require('fs');
3 +const api = require('./api');
4 +const Koa = require('koa');
5 +const Router = require("koa-router");
6 +const jwtMiddleware = require('./lib/jwtMiddleware');
7 +require('dotenv').config();
8 +const mongoose = require('mongoose');
9 +const bodyParser = require('koa-bodyparser');
10 +const port = process.env.PORT || 3000
11 +//443
12 +const app = new Koa();
13 +const router = new Router()
14 +const send = require('koa-send');
15 +var options = {
16 + key: fs.readFileSync('./server.key'),
17 + cert: fs.readFileSync('./server.crt'),
18 + allowHTTP1: true
19 +};
20 +//app.use(express.static('images'))
21 +
22 +mongoose.Promise = global.Promise; // Node 의 네이티브 Promise 사용
23 +// mongodb 연결
24 +mongoose.connect(process.env.MONGO_URI).then(
25 + (response) => {
26 + console.log('Successfully connected to mongodb');
27 + }
28 +).catch(e => {
29 + console.error(e);
30 +});
31 +
32 +var readFileThunk = function(src) {
33 + return new Promise(function (resolve, reject) {
34 + fs.readFile(src, {'encoding': 'utf8'}, function (err, data) {
35 + if(err) return reject(err);
36 + resolve(data);
37 + });
38 + });
39 +}
40 +//app.use(router.routes())
41 +/*
42 +app
43 + .use(router.routes())
44 + .use(router.allowedMethods());
45 + */
46 + app
47 + .use(jwtMiddleware)
48 + .use(bodyParser()) // bodyParser는 라우터 코드보다 상단에 있어야 합니다.
49 + .use(router.routes())
50 + .use(router.allowedMethods());
51 +
52 +
53 +
54 +/*
55 +router.get('/', (ctx, next) => {
56 + ctx.body = '루트 페이지 입니다.';
57 +});
58 +*/
59 +/*
60 +router.get('/', async (ctx, next) => {
61 + const rawContent = fs.readFileSync('index.html').toString('utf8')
62 + ctx.body = rawContent
63 +})*/
64 +
65 +router.get('/', function *(){
66 + this.body = yield readFileThunk(__dirname + '/public/index.html');
67 +})
68 +//router.use(api.routes());
69 +//app.use(router.routes()).use(router.allowedMethods())
70 +router.use('/api', api.routes());
71 +app.use(router.routes()).use(router.allowedMethods());
72 +
73 +http2
74 + .createSecureServer(options, app.callback())
75 + .listen(port, () => console.log("listening on port %i", port));
76 +//app.listen(port, function () {
77 +//console.log('server listening on port %d', port);
78 + //});
79 +
80 +
81 +
1 +const checkLoggedIn = (ctx, next) => {
2 + if (!ctx.state.user) {
3 + //debug
4 + console.log('checkLoggedin error');
5 + ctx.status = 401;
6 + return;
7 + }
8 + return next();
9 + };
10 + module.exports = checkLoggedIn;
11 +
12 +
...\ No newline at end of file ...\ No newline at end of file
1 +const config = {
2 + mailer: {
3 + user: "yoobinpark@khu.ac.kr",
4 + password: "1q2w3e4r!@",
5 + expiresIn: 60 * 5,
6 + },
7 + };
8 +
9 + module.exports = config;
...\ No newline at end of file ...\ No newline at end of file
1 +const jwt = require("jsonwebtoken");
2 +const User = require("../models/user");
3 +/*function generateToken(payload) {
4 + return new Promise((resolve, reject) => {
5 + jwt.sign(
6 + payload,
7 + jwtSecret,
8 + {
9 + expiresIn: '7d' // 토큰 유효기간 7일 설정
10 + }, (error, token) => {
11 + if (error) reject(error);
12 + resolve(token);
13 + }
14 + );
15 + }
16 + );
17 +};
18 +
19 +
20 +function decodeToken(token) {
21 + return new Promise(
22 + (resolve, reject) => {
23 + jwt.verify(token, jwtSecret, (error, decoded) => {
24 + if(error) reject(error);
25 + resolve(decoded);
26 + });
27 + }
28 + );
29 +}
30 +
31 +
32 +const jwtMiddleware = async (ctx, next) => {
33 + const token = ctx.cookies.get("access_token");
34 + if (!token) {
35 + return next();} //token이 없음
36 + try {
37 + const decoded = await decodeToken(token); // 토큰을 디코딩 합니다
38 + const user = await User.findById(decoded._id).exec();
39 + ctx.state.user = {
40 + _id: decoded._id,
41 + email: decoded.email
42 + };
43 + //특정 시간 남았으면 재발급
44 + const now = Math.floor(Date.now() / 1000);
45 + if (decoded.exp - now < 60 * 60 * 24 * 3.5) {
46 + const user = await User.findById(decoded._id);
47 + const token = user.generateToken();
48 + ctx.cookies.set("access_token", token, {
49 + maxAge: 1000 * 60 * 60 * 24 * 7, // 7일
50 + httpOnly: true
51 + });
52 + }
53 + ctx.request.user = decoded;
54 + return next();
55 + } catch (e) {
56 + //검증 실패
57 + return next();
58 + }
59 +};
60 +*/
61 +
62 +const jwtMiddleware = async (ctx, next) => {
63 + const token = ctx.cookies.get("access_token");
64 + if (!token) {
65 + return next();} //token이 없음
66 + try {
67 + const decoded = jwt.verify(token, process.env.JWT_SECRET);
68 + const user = await User.findById(decoded._id).exec();
69 + ctx.state.user = {
70 + _id: decoded._id,
71 + email: decoded.email
72 + };
73 + //특정 시간 남았으면 재발급
74 + const now = Math.floor(Date.now() / 1000);
75 + if (decoded.exp - now < 60 * 60 * 24 * 3.5) {
76 + const user = await User.findById(decoded._id);
77 + const token = user.generateToken();
78 + ctx.cookies.set("access_token", token, {
79 + maxAge: 1000 * 60 * 60 * 24 * 7, // 7일
80 + httpOnly: true,
81 + });
82 + }
83 +
84 + return next();
85 + } catch (e) {
86 + //검증 실패
87 + return next();
88 + }
89 +};
90 +
91 +module.exports = jwtMiddleware;
...\ No newline at end of file ...\ No newline at end of file
1 +const user = require('./user');
2 +const page = require('./page');
3 +const mongoose = require('mongoose');
4 +const { Schema } = mongoose;
5 +
6 +const bookSchema = new Schema({
7 + id: mongoose.Schema.Types.ObjectId,//unique number of page
8 + pages:[{type:String}],//book contains several pages. pages is the list of page id
9 + title: {type:String, require:true}, // book title
10 + author: [{type:String, require:true, default:user.user}],//작가복수 가능
11 + contents: {type:String}, // book subtitle or detail
12 + createDate: {type:Date, require:true, default:Date.now},
13 + updateDate: {type:Date, default:Date.now},
14 + views: {type: Number, default: 0},//how many people open this book
15 + favoritenum:{type: Number, default: 0},
16 + cover:{
17 + data: {type: Buffer,default:null},
18 + contentType: {type:String, default:null}
19 + },
20 + hashtag: [{type: String}],
21 + });
22 +
23 +
24 + bookSchema.statics.upload = async function ({title, author, contents, views, hashtag,cover}) {
25 + const page = new this({
26 + title: title,
27 + author: author,
28 + contents: contents,
29 + views: views,
30 + hashtag:hashtag,
31 + });
32 + await page.save(function(err){
33 + if(err) return console.error(err);
34 + });
35 + return page;
36 + };
37 +
38 +
39 + bookSchema.statics.ListofPage = async function () {
40 + var book = this;
41 + var pages = await page.find({"_id": book.ObjectId});
42 + return pages;
43 +};
44 +
45 + bookSchema.statics.findBySearchWord = async function (word) {
46 + var book = this;
47 + const reg = new RegExp(word, 'i');
48 + var result = []
49 + var books=await book.find();
50 +
51 + await books.map(obj => {
52 + // obj.hashtag.inclues
53 + if (obj.title.match(reg)) { //제목에 검색어가 들어가는가
54 + temp = new Object();
55 + temp.url = obj.url;
56 + temp.image = obj.image;
57 + temp.title = obj.title;
58 + temp.author = obj.author;
59 + result.push(temp);
60 + delete temp;
61 + }
62 + else if (obj.contents.match(reg))
63 + {
64 + temp = new Object();
65 + temp.url = obj.url;
66 + temp.image = obj.image;
67 + temp.title = obj.title;
68 + temp.author = obj.author;
69 + result.push(temp);
70 + delete temp;
71 + }
72 + else {
73 + for (let i = 0; i < obj.hashtag.length; i++)
74 + {
75 + if (obj.hashtag[i].match(reg)) { //hashtag에 검색어가 들어가는가
76 + temp = new Object();
77 + temp.url = obj.url;
78 + temp.image = obj.image;
79 + temp.title = obj.title;
80 + temp.author = obj.author;
81 + result.push(temp);
82 + delete temp;
83 + break
84 + }
85 + }
86 + }
87 + })
88 +
89 + return result
90 + }
91 +
92 + bookSchema.methods.updateB = async function (book) {
93 + this.title = book.title;
94 + this.author = book.author;
95 + this.contents = book.contents;
96 + this.author = book.author;
97 + if(book.cover != ""){
98 + this.cover = [];
99 + //this.cover.push(book.cover);
100 + }
101 + this.save();
102 + };
103 +
104 +
105 +
106 +module.exports = mongoose.model("Book", bookSchema);
...\ No newline at end of file ...\ No newline at end of file
1 +const user = require('./user');
2 +const mongoose = require('mongoose');
3 +const { Schema } = mongoose;
4 +
5 +const PageSchema = new Schema({
6 + id: mongoose.Schema.Types.ObjectId,//unique number of page
7 + book:{type:String},//book contains several pages
8 + title: {type:String, require:true}, // title of post
9 + author: [{type:String, require:true, default:user.user}],
10 + contents: {type:String}, // contents of page
11 + createDate: {type:Date, require:true, default:Date.now},
12 + updateDate: {type:Date, default:Date.now},
13 + views: {type: Number, default: 0},//how many people open this page
14 + cover:{
15 + data: {type: Buffer,default:null},
16 + contentType: {type:String, default:null}
17 + },
18 + hashtag: [{type: String}],
19 + comment: {
20 + writer: {type: String},
21 + contents: {type:String}, //comment text
22 + createDate: {type:Date, require:true, default:Date.now},
23 + updateDate: {type:Date, default:Date.now},
24 +
25 + },
26 + });
27 +
28 +
29 + PageSchema.statics.updateP = async function ({title, author, contents, hashtag,book,cover}) {
30 +
31 + const page = new this({
32 + title: title,
33 + book: book,//book으로 들어와서 생성한 경우, 그 book의 id를 넘겨주기
34 + author: author,
35 + contents: contents,
36 + hashtag:hashtag,
37 + cover:cover
38 +
39 + });
40 + await page.save(function(err){
41 + if(err) return console.error(err);
42 + });
43 + return page;
44 + };
45 +
46 +
47 + // parameters: search word
48 + PageSchema.statics.findBySearchWord = async function (word) {
49 + var page = this;
50 + const reg = new RegExp(word, 'i');
51 + var result = []
52 + var pages = await page.find();
53 +
54 + console.log(petType)
55 + await pages.map(obj => {
56 + // obj.hashtag.inclues
57 + if (obj.title.match(reg)) { //제목에 검색어가 들어가는가
58 + temp = new Object();
59 + temp.url = obj.url;
60 + temp.cover = obj.cover;
61 + temp.title = obj.title;
62 + temp.author = obj.author;
63 + result.push(temp);
64 + delete temp;
65 + }
66 + else {
67 + for (let i = 0; i < obj.hashtag.length; i++) {
68 + if (obj.hashtag[i].match(reg)) { //hashtag에 검색어가 들어가는가
69 + temp = new Object();
70 + temp.url = obj.url;
71 + temp.cover = obj.cover;
72 + temp.title = obj.title;
73 + temp.author = obj.author;
74 + result.push(temp);
75 + delete temp;
76 + break
77 + }
78 + }
79 + }
80 + })
81 +
82 + return result
83 + }
84 +
85 + // parameters: user's favorites page list
86 + PageSchema.statics.favoriteRecipe = async function (pageUrlArr) {
87 + var pgList = []
88 + for(let i=0; i<pageUrlArr.length; i++) {
89 + const page = await this.findOne({ url: pageUrlArr[i] }).exec();
90 +
91 + temp = new Object();
92 + temp.url = page.url;
93 + temp.title = page.title;
94 + temp.cover = page.cover;
95 + pgList.push(temp);
96 + delete temp;
97 + }
98 +
99 + return pgList;
100 + }
101 +
102 +module.exports = mongoose.model("Page", PageSchema);
...\ No newline at end of file ...\ No newline at end of file
1 +var mongoose = require("mongoose");
2 +var Schema = mongoose.Schema;
3 +const bcrypt = require("bcrypt");
4 +const jwt = require("jsonwebtoken");
5 +const crypto = require('crypto');
6 +//const Pet = require("./pet");
7 +
8 +const UserSchema = new Schema({
9 + //login require
10 + //email == id
11 + email: { type: String, required: true, unique: true },
12 + password: String,
13 + token: String,
14 + //user info
15 + username: String,
16 + phone: {type: String, require: true},
17 + nickname: {type: String, default: ""},
18 + books: [{type: String}],//array of bookid
19 + favorite: [{ type: String }],//String of url(book, page)
20 + });
21 +
22 +
23 +function hash(password) {
24 + return crypto.createHmac('sha256', process.env.SECRET_KEY).update(password).digest('hex');
25 +}
26 +UserSchema.statics.localRegister = function ({ nickname,phone, email, password }) {
27 + const user = new this({
28 + phone,
29 + email,
30 + password: hash(password),
31 + nickname
32 + });
33 +
34 + return user.save();
35 +};
36 + //User 모델에 정보를 save하기 전에 실행
37 + /*
38 +UserSchema.pre('save', function( next ){
39 + var user = this;
40 +
41 + //비밀번호를 바꿀때만 비밀번호를 암호화해준다
42 + if (user.isModified('password')) {
43 + // 비밀번호를 암호화 시킨다
44 + bcrypt.hash(user.password, 10, function (err, hash) { //hash: 암호화된 비밀번호
45 + if (err) return next(err);
46 + user.password = hash();
47 + next();
48 + });
49 +
50 + } else {
51 + next();
52 + }
53 + });
54 +
55 +*/
56 + // parameters: login user email, new password to change
57 +UserSchema.statics.updatePassword = async function (email, password) {
58 + const hash = await hash(password);
59 + this.findOneAndUpdate({email: email} , {$set: {password: hash}}, function(err, user) {
60 + if(err) throw err;
61 + console.log(user)
62 + })
63 +
64 + console.log("hash", hash);
65 + };
66 +
67 + UserSchema.methods.generateToken = function () {
68 + const token = jwt.sign(
69 + // 첫번째 파라미터엔 토큰 안에 집어넣고 싶은 데이터를 넣습니다
70 + {
71 + _id: this.id,
72 + email: this.email,
73 + },
74 + process.env.JWT_SECRET, // 두번째 파라미터에는 JWT 암호를 넣습니다
75 + {
76 + expiresIn: "7d", // 7일동안 유효함
77 + }
78 + );
79 + return token;
80 + };
81 +
82 +
83 +UserSchema.statics.updateFcm = async function (email, fcm){
84 + this.findOneAndUpdate({email: email}, {$set: {fcmToken: fcm}}, function(err,user){
85 + if(err) throw err;
86 + //console.log(user);
87 + })
88 + };
89 +
90 + //응답하는 JSON에서 비밀번호 정보 삭제
91 + UserSchema.methods.serialize = async function () {
92 + const data = this.toJSON();
93 + delete data.password;
94 + delete data._id;
95 + return data;
96 + };
97 +
98 +
99 + UserSchema.methods.checkPassword = async function (password) {
100 + const hashed = hash(password);
101 + return this.password === hashed;
102 + };
103 +
104 + //static method
105 + UserSchema.statics.findByEmail = async function (email) {
106 + return this.findOne({ email: email, logintype: "local" });
107 + };
108 +
109 +
110 + // parameters: user information to be updated
111 + UserSchema.statics.updateUser = async function (user) {
112 + this.findOneAndUpdate({ email: user.email }, { $set: user },
113 + function (err, result) {
114 + if (err) throw err;
115 + return result;
116 + });
117 + };
118 +
119 + // parameters: book's object id
120 + UserSchema.methods.addBook = async function (bookId) {
121 + console.log(bookId);
122 + this.books.push(bookId);
123 + this.save();
124 + }
125 +
126 +//parameters: login user email, pet's object id
127 +UserSchema.statics.delBook = async function (email, bookId) {
128 + return this.findOneAndUpdate({email: email}, {$pull: {books: bookId}});
129 +}
130 +
131 +// parameters: login user email, url of the book or page
132 +UserSchema.statics.updateFavorite = async function (email, contentsID) {
133 + return this.findOneAndUpdate(
134 + {
135 + email: email,
136 + },
137 + { $addToSet: { favorite: contentsID } }
138 + );
139 +};
140 +
141 +// parameters: login user email, url of the book or page
142 +UserSchema.statics.delFavorites = async function (email, contentsID) {
143 + return this.findOneAndUpdate(
144 + {
145 + email: email,
146 + },
147 + { $pull: { favorite: contentsID } }
148 + );
149 +};
150 +
151 +UserSchema.statics.showFavorites = async function (email) {
152 + this.books
153 + return (
154 + {
155 + email: email,
156 + },
157 + { $pull: { favorite: contentsID } }
158 + );
159 +};
160 +
161 +module.exports = mongoose.model("User", UserSchema, "Users");
...\ No newline at end of file ...\ No newline at end of file