-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver-3.js
145 lines (127 loc) · 3.51 KB
/
server-3.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
'use strict';
/**
* Step 2
* - Create User with plain-text UN/PW and store in DB
* - Update Basic Strategy to finduser and compare
*/
const express = require('express');
const passport = require('passport');
const mongoose = require('mongoose');
const { Strategy: LocalStrategy } = require('passport-local');
const { PORT, DATABASE_URL } = require('./config');
const app = express();
app.use(express.static('public'));
app.use(express.json());
// ===== Public endpoint =====
app.get('/api/welcome', function (req, res) {
res.json({message: 'Hello!'});
});
// ===== Define userSchema & User =====
const userSchema = new mongoose.Schema({
fullName: { type: String, default: '' },
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
});
userSchema.set('toJSON', {
virtuals: true, // include built-in virtual `id`
transform: (doc, result) => {
delete result._id;
delete result.__v;
delete result.password;
}
});
userSchema.methods.validatePassword = function (incomingPassword) {
const user = this; // for clarity
return incomingPassword === user.password;
};
const UserModel = mongoose.model('User', userSchema);
// ===== Define and create basicStrategy =====
const localStrategy = new LocalStrategy((username, password, done) => {
UserModel.findOne({ username })
.then(user => {
if (!user) {
return Promise.reject({
reason: 'LoginError',
message: 'Incorrect username',
location: 'username'
});
}
const isValid = user.validatePassword(password);
if (!isValid) {
return Promise.reject({
reason: 'LoginError',
message: 'Incorrect password',
location: 'password'
});
}
return done(null, user);
})
.catch(err => {
if (err.reason === 'LoginError') {
return done(null, false);
}
return done(err);
});
});
passport.use(localStrategy);
const localAuth = passport.authenticate('local', { session: false });
// ===== Protected endpoint =====
app.post('/api/login', localAuth, (req, res) => {
console.log(`${req.user.username} successfully logged in.`);
res.json({
message: 'Rosebud',
username: req.user.username
});
});
// ===== Post '/users' endpoint to save a new User =====
// saves a user with plain-text password to the DB
app.post('/api/users', (req, res, next) => {
// NOTE: validation removed for brevity
let { username, password, fullName } = req.body;
UserModel.find({ username })
.count()
.then(count => {
if (count > 0) {
return Promise.reject({
code: 422,
reason: 'ValidationError',
message: 'Username already taken',
location: 'username'
});
}
return UserModel.create({
username,
password,
fullName
});
})
.then(user => res.status(201).json(user))
.catch(err => {
if (err.reason === 'ValidationError') {
return next(err);
}
next({ code: 500, message: 'Internal server error' });
});
});
// Catch-all 404
app.use((req, res, next) => {
const err = new Error('Not Found');
err.code = 404;
next(err);
});
// Catch-all Error handler
app.use((err, req, res, next) => {
res.status(err.code || 500);
res.json({ message: err.message });
});
mongoose.connect(DATABASE_URL, { useNewUrlParser: true, useCreateIndex: true });
app.listen(PORT, function () {
console.log(`app listening on port ${this.address().port}`);
});