Showing
32 changed files
with
1102 additions
and
224 deletions
... | @@ -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": [ | ... | ... |
This diff is collapsed. Click to expand it.
... | @@ -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); | ... | ... |
src/css/master.css
deleted
100644 → 0
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 | ... | ... |
src/public/css/master.css
0 → 100644
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 | +} |
src/routes/book.js
0 → 100644
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 |
src/routes/page.js
0 → 100644
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; |
src/routes/user.js
0 → 100644
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 |
src/util.js
0 → 100644
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> | ... | ... |
-
Please register or login to post a comment