origin whitelist

This commit is contained in:
Jeremy Danyow 2019-01-27 15:07:15 -08:00
parent 569d161be5
commit 4eb2661d2c
No known key found for this signature in database
GPG Key ID: 50404A1CEB6B5250
3 changed files with 57 additions and 4 deletions

View File

@ -1,6 +1,7 @@
import { User, renderMarkdown } from './github';
import { scheduleMeasure } from './measure';
import { processRenderedMarkdown } from './comment-component';
import { getRepoConfig } from './repo-config';
// tslint:disable-next-line:max-line-length
const anonymousAvatar = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 16" version="1.1"><path fill="rgb(179,179,179)" fill-rule="evenodd" d="M8 10.5L9 14H5l1-3.5L5.25 9h3.5L8 10.5zM10 6H4L2 7h10l-2-1zM9 2L7 3 5 2 4 5h6L9 2zm4.03 7.75L10 9l1 2-2 3h3.22c.45 0 .86-.31.97-.75l.56-2.28c.14-.53-.19-1.08-.72-1.22zM4 9l-3.03.75c-.53.14-.86.69-.72 1.22l.56 2.28c.11.44.52.75.97.75H5l-2-3 1-2z"></path></svg>`;
@ -106,6 +107,7 @@ export class NewCommentComponent {
}
private handleInput = () => {
getRepoConfig(); // preload repo config
const text = this.textarea.value;
const isWhitespace = /^\s*$/.test(text);
this.submitButton.disabled = isWhitespace;

26
src/repo-config.ts Normal file
View File

@ -0,0 +1,26 @@
import { loadJsonFile } from './github';
import { pageAttributes } from './page-attributes';
export interface RepoConfig {
origins: string[];
}
let promise: Promise<RepoConfig>;
export function getRepoConfig() {
if (!promise) {
promise = loadJsonFile<RepoConfig>('utterances.json').then(
data => {
if (!Array.isArray(data.origins)) {
data.origins = [];
}
return data;
},
() => ({
origins: [pageAttributes.origin]
})
);
}
return promise;
}

View File

@ -1,4 +1,4 @@
import { pageAttributes as page } from './page-attributes';
import { pageAttributes as page, pageAttributes } from './page-attributes';
import {
Issue,
IssueComment,
@ -16,6 +16,7 @@ import { TimelineComponent } from './timeline-component';
import { NewCommentComponent } from './new-comment-component';
import { startMeasuring, scheduleMeasure } from './measure';
import { loadTheme } from './theme';
import { getRepoConfig } from './repo-config';
setRepoContext(page);
@ -46,6 +47,7 @@ function bootstrap(issue: Issue | null, user: User | null) {
const submit = async (markdown: string) => {
if (user) {
await assertOrigin();
if (!issue) {
issue = await createIssue(
page.issueTerm as string,
@ -75,11 +77,34 @@ function bootstrap(issue: Issue | null, user: User | null) {
addEventListener('not-installed', function handleNotInstalled() {
removeEventListener('not-installed', handleNotInstalled);
document.querySelector('.timeline')!.insertAdjacentHTML('afterbegin', `
<div class="flash flash-error flash-not-installed">
<div class="flash flash-error">
Error: utterances is not installed on <code>${page.owner}/${page.repo}</code>.
If you own this repo,
<a href="https://github.com/apps/utterances" target="_blank"><strong>install the app</strong></a>.
<a href="https://github.com/apps/utterances" target="_top"><strong>install the app</strong></a>.
Read more about this change in
<a href="https://github.com/utterance/utterances/pull/25" target="_blank">the PR</a>.
<a href="https://github.com/utterance/utterances/pull/25" target="_top">the PR</a>.
</div>`);
scheduleMeasure();
});
export async function assertOrigin() {
const { origins } = await getRepoConfig();
const { origin, owner, repo, url } = page;
if (origins.indexOf(origin) !== -1) {
return;
}
document.querySelector('.timeline')!.lastElementChild!.insertAdjacentHTML('beforebegin', `
<div class="flash flash-error flash-not-installed">
Error: <code>${origin}</code> is not permitted to post to <code>${owner}/${repo}</code>.
Confirm this is the correct repo for this site's comments. If you own this repo,
<a href="https://github.com/${owner}/${repo}/edit/master/utterances.json" target="_top">
<strong>update the utterances.json</strong>
</a>
to include <code>${origin}</code> in the list of origins.<br/><br/>
Suggested configuration:<br/>
<pre><code>${JSON.stringify({ origins: [origin] }, null, 2)}</code></pre>
</div>`);
scheduleMeasure();
throw new Error('Origin not permitted.');
}