mirror of
https://github.com/kevin-DL/sapper-template.git
synced 2026-01-13 10:45:34 +00:00
Some basic shell
This commit is contained in:
23
app/auth/db.js
Normal file
23
app/auth/db.js
Normal file
@@ -0,0 +1,23 @@
|
||||
// WARNING: THIS HELPER FILE IS NOT GOOD PRACTICE AND ONLY HERE FOR CONVENIENCE
|
||||
// use a real database for persisting users instead
|
||||
|
||||
// const Users = [{
|
||||
// username: 'general-zod',
|
||||
// email: 'general.zod@krypton.com',
|
||||
// hash: '',
|
||||
// }, {
|
||||
// username: 'kal-el',
|
||||
// email: 'kal-el@krypton.com',
|
||||
// hash: '',
|
||||
// }];
|
||||
const Users = [];
|
||||
|
||||
export default {
|
||||
find(key, value) {
|
||||
return Users.find(user => user[key] === value);
|
||||
},
|
||||
add(user) {
|
||||
Users.push(user);
|
||||
return user;
|
||||
},
|
||||
};
|
||||
95
app/auth/setup.js
Normal file
95
app/auth/setup.js
Normal file
@@ -0,0 +1,95 @@
|
||||
import passport from 'passport';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import bcrypt from 'bcrypt';
|
||||
import { Strategy as LocalStrategy } from 'passport-local';
|
||||
|
||||
// WARNING: use a database instead of persistent memory to store users
|
||||
// THE FOLLOWING IS BAD PRACTICE AND WILL NOT SCALE!!!
|
||||
// It's only here for convenience.
|
||||
import db from './db';
|
||||
|
||||
const env = process.env.NODE_ENV;
|
||||
|
||||
export function authSetup(app) {
|
||||
|
||||
passport.use(new LocalStrategy(async(username, password, done) => {
|
||||
try {
|
||||
const user = db.find('username', username);
|
||||
if (user) {
|
||||
const match = await bcrypt.compare(password, user.hash);
|
||||
if (!match) {
|
||||
return done(null, false, { message: `${user.username} is not authentic to that password.` });
|
||||
}
|
||||
done(null, { username: user.username, email: user.email });
|
||||
} else {
|
||||
return done(null, false, { message: `${username} does not exist.` });
|
||||
}
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
}));
|
||||
|
||||
app.use(passport.initialize());
|
||||
|
||||
app.post('/auth/signup', async(req, res, next) => {
|
||||
try {
|
||||
const { username, email, password } = req.body;
|
||||
|
||||
const userExists = db.find('username', username);
|
||||
const emailExists = db.find('email', email);
|
||||
|
||||
if (userExists || emailExists) {
|
||||
res.end(JSON.stringify({ userExists: !!userExists, emailExists: !!emailExists }));
|
||||
}
|
||||
|
||||
const user = db.add({
|
||||
username,
|
||||
email,
|
||||
hash: await bcrypt.hash(password, 10),
|
||||
});
|
||||
const userToSendToClient = { username: user.username, email: user.email };
|
||||
|
||||
// generate a signed son web token with the contents of user object and return it in the response
|
||||
const month = 60 * 60 * 24 * 30;
|
||||
const token = jwt.sign(userToSendToClient, config.JWT_SECRET, { expiresIn: month });
|
||||
res.cookie('ds', token, {
|
||||
// httpOnly: false,
|
||||
secure: env === 'production' ? true : false,
|
||||
maxAge: 1000 * month,
|
||||
});
|
||||
res.status(200).send({ userToSendToClient });
|
||||
} catch (error) {
|
||||
res.status(400).send({ error: 'req body should take the form { username, password }' });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/auth/local/login', (req, res) => {
|
||||
passport.authenticate('local', { session: false, successRedirect: '/', failureRedirect: '/login' }, (err, user) => {
|
||||
if (err || !user) {
|
||||
return res.status(400).json({
|
||||
message: 'Something went wrong.',
|
||||
user: user ? user : false,
|
||||
});
|
||||
}
|
||||
req.login(user, { session: false }, error => {
|
||||
if (error) {
|
||||
res.send(error);
|
||||
}
|
||||
// generate a signed son web token with the contents of user object and return it in the response
|
||||
const month = 60 * 60 * 24 * 30;
|
||||
const token = jwt.sign(user, config.JWT_SECRET, { expiresIn: month });
|
||||
return res.cookie('ds', token, {
|
||||
// httpOnly: false,
|
||||
secure: env === 'production' ? true : false,
|
||||
maxAge: 1000 * month,
|
||||
}).json(user);
|
||||
})
|
||||
})(req, res);
|
||||
});
|
||||
|
||||
app.post('/auth/logout', (req, res) => {
|
||||
req.logout();
|
||||
res.end('ok');
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,18 +1,35 @@
|
||||
import sirv from 'sirv';
|
||||
import polka from 'polka';
|
||||
// import bodyParser from 'body-parser';
|
||||
// import cookieParser from 'cookie-parser';
|
||||
import { authSetup } from './auth/setup';
|
||||
import sapper from 'sapper';
|
||||
import compression from 'compression';
|
||||
// import { Store } from 'svelte/store.js';
|
||||
// import { validate } from '../routes/_services/auth-check.js';
|
||||
import { manifest } from './manifest/server.js';
|
||||
|
||||
const { PORT, NODE_ENV } = process.env;
|
||||
const dev = NODE_ENV === 'development';
|
||||
|
||||
polka() // You can also use Express
|
||||
.use(
|
||||
compression({ threshold: 0 }),
|
||||
sirv('assets', { dev }),
|
||||
sapper({ manifest })
|
||||
)
|
||||
.listen(PORT, err => {
|
||||
const app = polka() // You can also use Express
|
||||
polka()
|
||||
app.use(compression({ threshold: 0 }))
|
||||
app.use(sirv('assets', { dev }))
|
||||
// app.use(bodyParser.json())
|
||||
// app.use(bodyParser.urlencoded({ extended: true }))
|
||||
// app.use(cookieParser())
|
||||
|
||||
authSetup(app)
|
||||
|
||||
app.use(sapper({
|
||||
manifest,
|
||||
store: req => {
|
||||
// const user = validate(req);
|
||||
// return new Store({ user: user.unauthorized ? null : user });
|
||||
},
|
||||
}))
|
||||
|
||||
app.listen(PORT, err => {
|
||||
if (err) console.log('error', err);
|
||||
})
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<!-- for the blog link, we're using rel=prefetch so that Sapper prefetches
|
||||
the blog data when we hover over the link or tap it on a touchscreen -->
|
||||
<li><a rel=prefetch class='{segment === "blog" ? "selected" : ""}' href='blog'>blog</a></li>
|
||||
<li><a class='{segment === "login" ? "selected" : ""}' href='login'>log in</a></li>
|
||||
<li><a class='{segment === "signup" ? "selected" : ""}' href='signup'>sign up</a></li>
|
||||
<li><span>sign out</span></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@@ -48,9 +51,10 @@
|
||||
bottom: -1px;
|
||||
}
|
||||
|
||||
a {
|
||||
a, span {
|
||||
text-decoration: none;
|
||||
padding: 1em 0.5em;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
5
routes/login.html
Normal file
5
routes/login.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<svelte:head>
|
||||
<title>Log In</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>Log In</h1>
|
||||
5
routes/signup.html
Normal file
5
routes/signup.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<svelte:head>
|
||||
<title>Sign Up</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>Sign Up</h1>
|
||||
Reference in New Issue
Block a user