mirror of
https://github.com/kevin-DL/sapper-template.git
synced 2026-01-21 22:15:00 +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 sirv from 'sirv';
|
||||||
import polka from 'polka';
|
import polka from 'polka';
|
||||||
|
// import bodyParser from 'body-parser';
|
||||||
|
// import cookieParser from 'cookie-parser';
|
||||||
|
import { authSetup } from './auth/setup';
|
||||||
import sapper from 'sapper';
|
import sapper from 'sapper';
|
||||||
import compression from 'compression';
|
import compression from 'compression';
|
||||||
|
// import { Store } from 'svelte/store.js';
|
||||||
|
// import { validate } from '../routes/_services/auth-check.js';
|
||||||
import { manifest } from './manifest/server.js';
|
import { manifest } from './manifest/server.js';
|
||||||
|
|
||||||
const { PORT, NODE_ENV } = process.env;
|
const { PORT, NODE_ENV } = process.env;
|
||||||
const dev = NODE_ENV === 'development';
|
const dev = NODE_ENV === 'development';
|
||||||
|
|
||||||
polka() // You can also use Express
|
const app = polka() // You can also use Express
|
||||||
.use(
|
polka()
|
||||||
compression({ threshold: 0 }),
|
app.use(compression({ threshold: 0 }))
|
||||||
sirv('assets', { dev }),
|
app.use(sirv('assets', { dev }))
|
||||||
sapper({ manifest })
|
// app.use(bodyParser.json())
|
||||||
)
|
// app.use(bodyParser.urlencoded({ extended: true }))
|
||||||
.listen(PORT, err => {
|
// 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);
|
if (err) console.log('error', err);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
<!-- for the blog link, we're using rel=prefetch so that Sapper prefetches
|
<!-- 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 -->
|
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 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>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@@ -48,9 +51,10 @@
|
|||||||
bottom: -1px;
|
bottom: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a, span {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 1em 0.5em;
|
padding: 1em 0.5em;
|
||||||
display: block;
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</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