Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Sapper session handling (creation and updating). Idk if this is the best way of doing things but at least it *works*. Feel free to scrutinize this code and let me know all the ways it sucks.
<script>
// import
import { onMount } from "svelte";
// util
import { metadata } from "~util";
// redirect
onMount(() => {
// `location.replace` forces a hard refresh in the browser,
// which pulls fresh session data from the server
setTimeout(() => location.replace("/"), 2500);
});
</script>
<style type="text/scss">
.splash {
text-align: center;
h2 {
font-size: 2rem;
margin-bottom: 1rem;
}
p {
font-size: 1rem;
line-height: 1.33;
margin-bottom: 0.25rem;
}
}
</style>
<svelte:head>
<title>Authenticating {metadata.separator} {metadata.title}</title>
</svelte:head>
<section class="splash">
<h2>Authenticating</h2>
<p>Redirection in T minus 2.5 seconds...</p>
</section>
<script context="module">
export async function preload(page, session) {
return fetch(SITE + "/logout", {
body: JSON.stringify(session),
headers: {
"Content-Type": "application/json",
},
method: "POST"
});
}
</script>
<script>
// imports
import { goto, stores } from "@sapper/app";
import { onMount } from "svelte";
// utils
import { metadata } from "~util";
const { session } = stores();
session.set({}); // empty the session so the UI (nav) updates
// redirect
onMount(() => {
// `location.replace` forces a hard refresh in the browser,
// which pulls fresh session data from the server
setTimeout(() => location.replace("/"), 2500);
});
</script>
<style type="text/scss">
.splash {
text-align: center;
h2 {
font-size: 2rem;
margin-bottom: 1rem;
}
p {
font-size: 1rem;
line-height: 1.33;
margin-bottom: 0.25rem;
}
}
</style>
<svelte:head>
<title>Til' we meet again! {metadata.separator} {metadata.title}</title>
</svelte:head>
<section class="splash">
<h2>Logout successful</h2>
<p>See ya later!</p>
<p>Redirection in T minus 2.5 seconds...</p>
</section>
"use strict";
// I M P O R T S
import "isomorphic-unfetch";
import * as sapper from "@sapper/server";
import bodyParser from "body-parser";
import compression from "compression";
import env from "vne";
import polka from "polka";
import session from "express-session";
import sirv from "sirv";
import store from "connect-redis";
// U T I L S
import { graphql } from "~util";
import { sessionCreateQuery } from "~query";
const { PORT, NODE_ENV } = process.env;
const isDevMode = NODE_ENV === "development";
const RedisStore = store(session);
const redisOptions = {
host: "localhost",
logErrors: true,
port: 6379, // default port
prefix: "myapp:",
ttl: 6.04e+8
};
// P R O G R A M
polka()
.use(bodyParser.json())
.use(session({
cookie: {
maxAge: 6.04e+8 // week in seconds
},
resave: false,
rolling: true,
saveUninitialized: true,
secret: env.key.secret,
store: new RedisStore(redisOptions)
}))
.use(compression({ threshold: 0 }))
.use(sirv("static", { dev: isDevMode }))
.use(authenticate)
.use(sapper.middleware({
session: (requestObject, responseObject) => { // eslint-disable-line no-unused-vars
return {
id: requestObject.session && requestObject.session.sessionId ?
requestObject.session.sessionId :
null,
user: requestObject.session && requestObject.session.sessionUser ?
requestObject.session.sessionUser :
null
};
}
}))
// These two are important for some reason
.get("*", () => {})
.post("*", () => {})
.listen(PORT, err => {
if (err)
console.error("error", err);
});
// H E L P E R S
function authenticate(requestObject, responseObject, next) {
if (requestObject.params.wild === "access") {
if (
requestObject.session &&
requestObject.session.user &&
Object.keys(requestObject.session.user).length > 0 && requestObject.session.id
) return (401, responseObject.end("...are you not logged in already?<br/><a href='/' title='Go back home'>Go back home</a>"));
if (
!requestObject.query ||
!requestObject.query.token ||
!requestObject.query.uid
) return (401, responseObject.end("Unauthorized<br/><a href='/' title='Go home'>Go home</a>"));
const { token, uid } = requestObject.query;
graphql(sessionCreateQuery, { email: uid, token })
.then(response => {
response = response.createSession;
if (response.success) {
requestObject.session.sessionId = response.session;
requestObject.session.sessionUser = response.user;
requestObject.session.save(err => {
if (err) {
console.error(err); // TODO: Log this
return (500, responseObject.end("Session save error...try again?<br/><a href='/' title='Go home'>Go home</a>"));
}
});
}
});
}
if (requestObject.method === "POST" && requestObject.url === "/settings") {
// TODO:
// Check credentials with API before updating session
requestObject.session.sessionUser = requestObject.body;
requestObject.session.save(err => {
if (err) {
console.error(err); // TODO: Log this
return (500, responseObject.end("Session save error...try again?"));
}
});
}
if (requestObject.method === "POST" && requestObject.url === "/logout") {
if (
!requestObject.session ||
!requestObject.session.sessionUser ||
!requestObject.session.sessionId
) return (401, responseObject.end("Unauthorized<br/>Log <em>in</em> before you try to log <em>out</em>."));
requestObject.session.destroy(err => {
if (err) {
console.error(err); // TODO: Log this
return (500, responseObject.end("Logout error...try again?<br/><a href='/' title='Go home'>Go home</a>"));
}
});
}
next();
}
<script>
// SITE is a global variable
function deleteUserSession(data) {
return fetch(SITE + "/logout", {
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json"
},
method: "POST"
});
}
function updateUserSession(data) {
return fetch(SITE + "/settings", {
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json"
},
method: "POST"
})
.then(response => response); // This line is probably not important
}
</script>
<!--
...more stuff but not important
-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.