Skip to content

Commit

Permalink
Merge branch 'cookies' into gh-3019
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Aug 18, 2019
2 parents 419b415 + 37b8848 commit 90ecf90
Show file tree
Hide file tree
Showing 20 changed files with 263 additions and 251 deletions.
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,8 @@
"sourceMap": true,
"instrument": true
},
"dependencies": {}
"dependencies": {
"cookie": "^0.4.0",
"flru": "^1.0.2"
}
}
15 changes: 15 additions & 0 deletions site/migrations/002-create-sessions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
exports.up = DB => {
DB.sql(`
create table if not exists sessions (
uid uuid NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(),
user_id integer REFERENCES users(id) not null,
expiry timestamp without time zone DEFAULT now() + interval '1 year'
);
`);
};

exports.down = DB => {
DB.sql(`
drop table if exists sessions;
`);
};
5 changes: 5 additions & 0 deletions site/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"polka": "^1.0.0-next.4",
"prismjs": "^1.17.1",
"sirv": "^0.4.2",
"uuid": "^3.3.2",
"yootils": "0.0.16"
},
"devDependencies": {
Expand Down
150 changes: 0 additions & 150 deletions site/src/backend/auth.js

This file was deleted.

22 changes: 0 additions & 22 deletions site/src/backend/token.js

This file was deleted.

6 changes: 6 additions & 0 deletions site/src/routes/auth/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const oauth = 'https://github.com/login/oauth';
export const baseurl = process.env.BASEURL;
export const secure = baseurl.startsWith('https:');

export const client_id = process.env.GITHUB_CLIENT_ID;
export const client_secret = process.env.GITHUB_CLIENT_SECRET;
54 changes: 54 additions & 0 deletions site/src/routes/auth/callback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import send from '@polka/send';
import devalue from 'devalue';
import * as cookie from 'cookie';
import * as httpie from 'httpie';
import { parse, stringify } from 'querystring';
import { sanitize_user, create_user, create_session } from '../../utils/auth';
import { oauth, secure, client_id, client_secret } from './_config.js';

export async function get(req, res) {
try {
// Trade "code" for "access_token"
const r1 = await httpie.post(`${oauth}/access_token?` + stringify({
code: req.query.code,
client_id,
client_secret,
}));

// Now fetch User details
const { access_token } = parse(r1.data);
const r2 = await httpie.get('https://api.github.com/user', {
headers: {
'User-Agent': 'svelte.dev',
Authorization: `token ${access_token}`
}
});

const user = await create_user(r2.data, access_token);
const session = await create_session(user);

res.writeHead(200, {
'Set-Cookie': cookie.serialize('sid', session.uid, {
maxAge: 31536000,
path: '/',
httpOnly: true,
secure
}),
'Content-Type': 'text/html; charset=utf-8'
});

res.end(`
<script>
window.opener.postMessage({
user: ${devalue(sanitize_user(user))}
}, window.location.origin);
</script>
`);
} catch (err) {
console.error('GET /auth/callback', err);
send(res, 500, err.data, {
'Content-Type': err.headers['content-type'],
'Content-Length': err.headers['content-length']
});
}
}
27 changes: 27 additions & 0 deletions site/src/routes/auth/login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import send from '@polka/send';
import { stringify } from 'querystring';
import { oauth, baseurl, client_id } from './_config.js';

export const get = client_id
? (req, res) => {
const Location = `${oauth}/authorize?` + stringify({
scope: 'read:user',
client_id,
redirect_uri: `${baseurl}/auth/callback`,
});

send(res, 302, Location, { Location });
}
: (req, res) => {
send(res, 500, `
<body style="font-family: sans-serif; background: rgb(255,215,215); border: 2px solid red; margin: 0; padding: 1em;">
<h1>Missing .env file</h1>
<p>In order to use GitHub authentication, you will need to <a target="_blank" href="https://github.com/settings/developers">register an OAuth application</a> and create a local .env file:</p>
<pre>GITHUB_CLIENT_ID=[YOUR_APP_ID]\nGITHUB_CLIENT_SECRET=[YOUR_APP_SECRET]\nBASEURL=http://localhost:3000</pre>
<p>The <code>BASEURL</code> variable should match the callback URL specified for your app.</p>
<p>See also <a target="_blank" href="https://github.com/sveltejs/svelte/tree/master/site#repl-github-integration">here</a></p>
</body>
`, {
'Content-Type': 'text/html; charset=utf-8'
});
};
17 changes: 17 additions & 0 deletions site/src/routes/auth/logout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import send from '@polka/send';
import * as cookie from 'cookie';
import { secure } from './_config.js';
import { delete_session } from '../../utils/auth.js';

export async function get(req, res) {
await delete_session(req.cookies.sid);

send(res, 200, '', {
'Set-Cookie': cookie.serialize('sid', '', {
maxAge: -1,
path: '/',
httpOnly: true,
secure
})
});
}
8 changes: 0 additions & 8 deletions site/src/routes/auth/me.json.js

This file was deleted.

15 changes: 12 additions & 3 deletions site/src/routes/repl/[id]/_components/AppControls/UserMenu.svelte
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
<script>
import { user, logout } from '../../../../../user.js';
import { stores } from '@sapper/app';
const { session } = stores();
const logout = async () => {
const r = await fetch(`/auth/logout`, {
credentials: 'include'
});
if (r.ok) $session.user = null;
}
let showMenu = false;
let name;
$: name = $user.name || $user.username;
$: name = $session.user.name || $session.user.username;
</script>

<div class="user" on:mouseenter="{() => showMenu = true}" on:mouseleave="{() => showMenu = false}">
<span>{name}</span>
<img alt="{name} avatar" src="{$user.avatar}">
<img alt="{name} avatar" src="{$session.user.avatar}">

{#if showMenu}
<div class="menu">
Expand Down
Loading

0 comments on commit 90ecf90

Please sign in to comment.