Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] GitHub authentication #224

Merged
merged 22 commits into from
Mar 25, 2018
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ assets/svelte-app.zip
credentials.json
app/manifest
build
yarn-error.log
yarn-error.log
.env
.sessions
14 changes: 13 additions & 1 deletion app/client.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import { init } from 'sapper/runtime.js';
import store from '../client/store.js';
import { routes } from './manifest/client.js';

init(document.querySelector('#sapper'), routes);
init(document.querySelector('#sapper'), routes, {
store: data => {
store.set(data);

fetch(`api/guide/contents`).then(r => r.json()).then(guide_contents => {
store.set({ guide_contents });
});

window.store = store;
return store;
}
});

if (navigator.serviceWorker && navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.onstatechange = function(e) {
Expand Down
94 changes: 93 additions & 1 deletion app/server.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,107 @@
import dotenv from 'dotenv';
import express from 'express';
import compression from 'compression';
import session from 'express-session';
import passport from 'passport';
import { Strategy } from 'passport-github';
import sessionFileStore from 'session-file-store';
import sapper from 'sapper';
import serve from 'serve-static';
import devalue from 'devalue';
import { Store } from 'svelte/store.js';
import { routes } from './manifest/server.js';

dotenv.config();

const FileStore = sessionFileStore(session);

passport.use(new Strategy({
clientID: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
callbackURL: `http://${process.env.ORIGIN}/auth/callback`
}, (accessToken, refreshToken, profile, callback) => {
console.log(profile);

return callback(null, {
id: profile.id,
username: profile.username,
displayName: profile.displayName,
photo: profile.photos && profile.photos[0] && profile.photos[0].value,

accessToken
});
}));

passport.serializeUser((user, cb) => {
cb(null, user);
});

passport.deserializeUser((obj, cb) => {
cb(null, obj);
});

express()
.use(compression({ threshold: 0 }))

.use(session({
secret: 'svelte',
resave: true,
saveUninitialized: true,
cookie: {
maxAge: 31536000
},
store: new FileStore({
path: process.env.NOW ? `/tmp/sessions` : `.sessions`
})
}))

.use(passport.initialize())
.use(passport.session())

.get('/auth/login', (req, res, next) => {
const { returnTo } = req.query;
req.session.returnTo = returnTo ? decodeURIComponent(returnTo) : '/';
next();
}, passport.authenticate('github', { scope: ['gist', 'read:user'] }))

.post('/auth/logout', (req, res) => {
req.logout();
res.end('ok');
})

.get('/auth/callback', passport.authenticate('github', { failureRedirect: '/auth/error' }), (req, res) => {
const user = req.session.passport && req.session.passport.user;
if (user) delete user.accessToken;

res.end(`
<script>
window.parent.postMessage({
user: ${devalue(user)}
}, window.location.origin);
</script>
`);
})

.use(
compression({ threshold: 0 }),
serve('assets'),
sapper({
routes
routes,
store: req => {
const user = req.session.passport && req.session.passport.user;

return new Store({
user: user && {
// strip access token
id: user.id,
name: user.name,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be username: user.username.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, you're right — fixed

displayName: user.displayName,
photo: user.photo
},
guide_contents: []
});
}
})
)

.listen(process.env.PORT);
4 changes: 4 additions & 0 deletions assets/icons/download.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 3 additions & 13 deletions assets/icons/flip.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/icons/fork.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/icons/link.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/icons/save.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions client/store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Store } from 'svelte/store.js';

class ClientStore extends Store {
logout() {
return fetch(`auth/logout`, {
method: 'POST',
credentials: 'include'
}).then(() => {
this.set({ user: null });
});
}
}

export default new ClientStore();
44 changes: 26 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,43 +31,51 @@
"devDependencies": {
"chalk": "^2.0.1",
"clean-css": "^4.0.12",
"css-loader": "^0.28.7",
"degit": "^2.0.1",
"eslint": "^4.0.0",
"css-loader": "^0.28.11",
"degit": "^2.1.3",
"eslint": "^4.19.1",
"eslint-plugin-html": "^4.0.2",
"eslint-plugin-import": "^2.2.0",
"git-branch-is": "^0.1.0",
"glob": "^7.1.2",
"html-entities": "^1.2.1",
"now": "^10.1.5",
"now": "^10.2.1",
"style-loader": "^0.20.3",
"svelte": "^1.57.1",
"svelte-loader": "^2.5.0",
"webpack": "^4.1.0"
"svelte": "^1.58.2",
"svelte-loader": "^2.5.1",
"webpack": "^4.2.0",
"workerize-loader": "^1.0.2"
},
"dependencies": {
"codemirror": "^5.25.2",
"codemirror": "^5.36.0",
"compression": "^1.6.2",
"cross-env": "^5.1.1",
"express": "^4.15.2",
"file-saver": "^1.3.3",
"cross-env": "^5.1.4",
"devalue": "^1.0.1",
"dotenv": "^5.0.1",
"express": "^4.16.3",
"express-session": "^1.15.6",
"file-saver": "^1.3.8",
"highlight.js": "^9.12.0",
"jszip": "^3.1.3",
"locate-character": "^2.0.0",
"lru-cache": "^4.1.1",
"marked": "^0.3.7",
"locate-character": "^2.0.5",
"lru-cache": "^4.1.2",
"marked": "^0.3.18",
"needle": "^2.0.0",
"node-fetch": "^2.1.1",
"rollup": "^0.56.5",
"passport": "^0.4.0",
"passport-github": "^1.1.0",
"rollup": "^0.57.1",
"sapper": "^0.10.1",
"serve-static": "^1.13.1",
"sourcemap-codec": "^1.3.1"
"session-file-store": "^1.2.0",
"sourcemap-codec": "^1.4.1"
},
"now": {
"env": {
"NODE_ENV": "production",
"client_id": "@svelte-gist-client-id",
"client_secret": "@svelte-gist-client-secret"
"ORIGIN": "svelte.technology",
"GITHUB_CLIENT_ID": "@svelte-gist-client-id",
"GITHUB_CLIENT_SECRET": "@svelte-gist-client-secret"
},
"alias": "svelte.technology",
"files": [
Expand Down
5 changes: 1 addition & 4 deletions routes/4xx.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,10 @@ <h1>{{error.message}}</h1>

<script>
import Layout from './_components/Layout.html';
import store from './_store.js';

export default {
components: {
Layout
},

store: () => store
}
};
</script>
5 changes: 1 addition & 4 deletions routes/5xx.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,10 @@ <h1>{{error.message}}</h1>

<script>
import Layout from './_components/Layout.html';
import store from './_store.js';

export default {
components: {
Layout
},

store: () => store
}
};
</script>
15 changes: 0 additions & 15 deletions routes/_store.js

This file was deleted.

3 changes: 0 additions & 3 deletions routes/api/gists/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ try {
// noop
}

console.log(`has client_id: ${!!credentials.id}`);
console.log(`has client_secret: ${!!credentials.secret}`);

export function post(req, res) {
let body = '';

Expand Down
3 changes: 0 additions & 3 deletions routes/blog/[slug].html
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,12 @@ <h1>{{post.metadata.title}}</h1>

<script>
import Layout from '../_components/Layout.html';
import store from '../_store.js';

export default {
components: {
Layout
},

store: () => store,

preload({ params }) {
return this.fetch(`api/blog/${params.slug}`).then(r => r.json()).then(post => {
return { post };
Expand Down
3 changes: 0 additions & 3 deletions routes/blog/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,12 @@ <h2>{{post.metadata.title}}</h2>

<script>
import Layout from '../_components/Layout.html';
import store from '../_store.js';

export default {
components: {
Layout
},

store: () => store,

preload() {
return this.fetch(`api/blog`).then(r => r.json()).then(posts => {
return { posts };
Expand Down
1 change: 0 additions & 1 deletion routes/guide/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ <h2>{{section.metadata.title}}</h2>
</style>

<script>
import store from '../_store.js';
import GuideContents from '../_components/GuideContents.html';
import Layout from '../_components/Layout.html';

Expand Down
5 changes: 1 addition & 4 deletions routes/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,10 @@ <h2>The magical disappearing UI framework</h2>

<script>
import Layout from './_components/Layout.html';
import store from './_store.js';

export default {
components: {
Layout
},

store: () => store
}
};
</script>
Loading