Skip to content

Instantly share code, notes, and snippets.

@NetOpWibby
Last active August 22, 2021 21:18
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save NetOpWibby/17198f444896be4596dfbb2dc88993c4 to your computer and use it in GitHub Desktop.
Save NetOpWibby/17198f444896be4596dfbb2dc88993c4 to your computer and use it in GitHub Desktop.
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