reauth and terms:

- use modal display from sw message to request auth, as redirect may be on a non-html page
- also use modal for terms to avoid leaving page
This commit is contained in:
Ilya Kreymer
2020-05-07 15:13:04 -07:00
parent 4af7983355
commit b548e2fc15
3 changed files with 198 additions and 153 deletions
+84 -58
View File
File diff suppressed because one or more lines are too long
+106 -87
View File
@@ -56,7 +56,6 @@ class AppMain extends LitElement
navMenuShown: { type: Boolean }, navMenuShown: { type: Boolean },
showTerms: { type: Boolean }, showTerms: { type: Boolean },
sourceLoaded: { type: Boolean }, sourceLoaded: { type: Boolean },
gdriveReAuth: { type: String }
} }
} }
@@ -74,7 +73,6 @@ class AppMain extends LitElement
render() { render() {
return html` return html`
${!this.gdriveReAuth ? html`
<div class="container" style="display: sticky"> <div class="container" style="display: sticky">
<nav class="navbar breadcrumbs" role="navigation" aria-label="main navigation"> <nav class="navbar breadcrumbs" role="navigation" aria-label="main navigation">
<div class="navbar-brand"> <div class="navbar-brand">
@@ -97,65 +95,57 @@ class AppMain extends LitElement
</div>` : html``} </div>` : html``}
</div> </div>
<div class="navbar-end"> <div class="navbar-end">
<a href="?terms" class="navbar-item">Terms</a> <a href="?terms" @click="${(e) => { e.preventDefault(); this.showTerms = true} }"class="navbar-item">Terms</a>
<a href="/docs" class="navbar-item"> <a href="/docs" target="_blank" class="navbar-item">
<fa-icon .svg="${fasHelp}"></fa-icon>&nbsp;Docs <fa-icon .svg="${fasHelp}"></fa-icon>&nbsp;Docs
</a> </a>
</div> </div>
</nav> </nav>
</div>` : html``} </div>
${this.renderContent()}
`;
}
renderContent() { ${this.sourceUrl ? html`
if (this.gdriveReAuth) { <wr-coll .loadInfo="${this.loadInfo}"
return html` sourceUrl="${this.sourceUrl}"
<div class="hero is-fullheight"> @replay-favicons=${this.onFavIcons}
<div class="hero-body"> @coll-loaded=${this.onCollLoaded}></wr-coll>
<div class="container has-text-centered"> ` : html`
<wr-gdrive .fileId=${this.gdriveReAuth} .reauth="${true}" @load-ready=${this.onReAuthed}/> <wr-index @load-start=${this.onStartLoad}></wr-index>
</div> `}
</div> ${this.showTerms ? html`
</div> <div class="modal is-active">
`; <div class="modal-background"></div>
} else if (this.sourceUrl) { <div class="modal-card">
return html` <header class="modal-card-head">
<wr-coll .loadInfo="${this.loadInfo}" <p class="modal-card-title">Terms and Privacy</p>
sourceUrl="${this.sourceUrl}" <button class="delete" aria-label="close" @click="${(e) => this.showTerms = false}"></button>
@replay-favicons=${this.onFavIcons} </header>
@coll-loaded=${this.onCollLoaded}></wr-coll> <section class="modal-card-body">
`; <div class="container">
} else if (this.showTerms) { <div class="content">
return html` <p>This site is a static browser-based application that loads web archive files provided by the user
<div class="container"> and renders them for replay in the browser.</p>
<div class="content"> <p>The site is operated by the <a href="https://webrecorder.net/">Webrecorder Project</a></p>
<h3 class="title">Terms</h3> <p>See the <a target="_blank" href="/docs">Docs</a> for more info on how it works.</p>
<p>This site is a static browser-based application that loads web archive files provided by the user
and renders them for replay in the browser.</p>
<p>The site is operated by the <a href="https://webrecorder.net/">Webrecorder Project</a></p>
<p>See the <a href="/docs">About</a> for more info on how it works.</p>
<h3>Privacy</h3> <h3>Privacy</h3>
<p><b>No data is uploaded anywhere and no information is collected.</b></p> <p><b>No data is uploaded anywhere and no information is collected.</b></p>
<p>All content rendered stays directly in your browser.</p> <p>All content rendered stays directly in your browser.</p>
<h4>Disclaimer of Warranties</h4> <h4>Disclaimer of Warranties</h4>
<p>The application may not always be available. No guarantees!</p> <p>The application may not always be available. No guarantees!</p>
<p>Some legalese:</p> <p>Some legalese:</p>
<p style="font-size: 0.8rem">DISCLAIMER OF SOFTWARE WARRANTY. WEBRECORDER SOFTWARE PROVIDES THIS SOFTWARE TO YOU "AS AVAILABLE" <p style="font-size: 0.8rem">DISCLAIMER OF SOFTWARE WARRANTY. WEBRECORDER SOFTWARE PROVIDES THIS SOFTWARE TO YOU "AS AVAILABLE"
AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
INCLUDING WITHOUT LIMITATION ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. INCLUDING WITHOUT LIMITATION ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
</p> </p>
<a class="button is-primary" href="#" @click="${(e) => window.history.back()}">Back</a> <a class="button is-primary" href="#" @click="${(e) => this.showTerms = false}">Close</a>
</div> </div>
</div>
</section>
</div> </div>
`; <button class="modal-close is-large" aria-label="close"></button>
} else if (this.sourceUrl === "") { </div>
return html` ` : ``} `
<wr-index @load-start=${this.onStartLoad}></wr-index>
`;
}
} }
firstUpdated() { firstUpdated() {
@@ -168,22 +158,6 @@ class AppMain extends LitElement
} }
} }
async onReAuthed(event) {
const redir = this.pageParams.get("redirUrl");
const {coll} = await sourceToId(this.sourceUrl);
const headers = event.detail.headers;
const resp = await fetch(`/wabac/api/${coll}/updateAuth`, {
method: 'POST',
body: JSON.stringify({headers})
});
if (redir) {
window.location.href = redir;
}
}
onFavIcons(event) { onFavIcons(event) {
const head = document.querySelector('head'); const head = document.querySelector('head');
const oldLinks = document.querySelectorAll("link[rel*='icon']"); const oldLinks = document.querySelectorAll("link[rel*='icon']");
@@ -225,11 +199,6 @@ class AppMain extends LitElement
this.sourceUrl = this.pageParams.get("source") || ""; this.sourceUrl = this.pageParams.get("source") || "";
//todo: make more generic?
if (this.pageParams.get("autherr") && this.pageParams.get("redirUrl") && this.sourceUrl.startsWith("googledrive://")) {
this.gdriveReAuth = this.sourceUrl.slice("googledrive://".length);
}
if (this.pageParams.has("terms")) { if (this.pageParams.has("terms")) {
this.showTerms = true; this.showTerms = true;
} }
@@ -333,7 +302,6 @@ class WrLoader extends LitElement
switch (scheme) { switch (scheme) {
case "googledrive": case "googledrive":
this.state = "googledrive"; this.state = "googledrive";
this.fileId = host;
source = await this.googledriveInit(); source = await this.googledriveInit();
break; break;
@@ -442,7 +410,7 @@ class WrLoader extends LitElement
renderContent() { renderContent() {
switch (this.state) { switch (this.state) {
case "googledrive": case "googledrive":
return html`<wr-gdrive .fileId=${this.fileId} @load-ready=${this.onLoadReady}/>` return html`<wr-gdrive .sourceId=${this.sourceUrl} @load-ready=${this.onLoadReady}/>`
case "started": case "started":
return html` return html`
@@ -1376,6 +1344,8 @@ class WrReplayPage extends LitElement
this.url = ""; this.url = "";
this.ts = ""; this.ts = "";
this.title = ""; this.title = "";
this.authNeeded = null;
} }
static get properties() { static get properties() {
@@ -1392,12 +1362,19 @@ class WrReplayPage extends LitElement
title: { type: String }, title: { type: String },
iframeUrl: { type: String }, iframeUrl: { type: String },
isLoading: { type: Boolean } isLoading: { type: Boolean },
authNeeded: { type: Object }
} }
} }
firstUpdated() { firstUpdated() {
window.addEventListener("message", (event) => this.onReplayMessage(event)); window.addEventListener("message", (event) => this.onReplayMessage(event));
navigator.serviceWorker.addEventListener("message", (event) => {
if (event.data.type === "authneeded") {
this.authNeeded = event.data;
}
});
} }
doSetIframeUrl() { doSetIframeUrl() {
@@ -1456,9 +1433,12 @@ class WrReplayPage extends LitElement
return false; return false;
} }
onRefresh(event) { onRefresh(event, forceReload) {
event.preventDefault(); if (event) {
if (this.isLoading) { event.preventDefault();
}
if (this.isLoading && !forceReload) {
return; return;
} }
@@ -1513,6 +1493,11 @@ class WrReplayPage extends LitElement
#refresh { #refresh {
border: 0px; border: 0px;
} }
.modal {
top: 174px;
}
`); `);
} }
@@ -1546,8 +1531,43 @@ class WrReplayPage extends LitElement
<iframe @message="${this.onReplayMessage}" <iframe @message="${this.onReplayMessage}"
src="${this.iframeUrl}"></iframe> src="${this.iframeUrl}"></iframe>
` : ``} ` : ``}
${this.authNeeded ? html`
<div class="modal is-active">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Auth Needed</p>
<button class="delete" aria-label="close" @click="${(e) => this.authNeeded = null}"></button>
</header>
<section class="modal-card-body">
<div class="container has-text-centered">
<wr-gdrive .sourceId=${this.authNeeded.source} .reauth="${true}" @load-ready=${this.onReAuthed}/>
</div>
</section>
</div>
<button class="modal-close is-large" aria-label="close"></button>
</div>
` : ``}
`; `;
} }
async onReAuthed(event) {
if (!this.authNeeded) {
return;
}
const headers = event.detail.headers;
const resp = await fetch(`/wabac/api/${this.authNeeded.coll}/updateAuth`, {
method: 'POST',
body: JSON.stringify({headers})
});
this.authNeeded = false;
this.onRefresh(null, true);
}
} }
// =========================================================================== // ===========================================================================
@@ -1556,7 +1576,7 @@ class WrGdrive extends LitElement
constructor() { constructor() {
super(); super();
this.manual = false; this.manual = false;
this.fileId = ""; this.sourceId = "";
this.scriptLoaded = false; this.scriptLoaded = false;
this.error = false; this.error = false;
} }
@@ -1564,14 +1584,14 @@ class WrGdrive extends LitElement
static get properties() { static get properties() {
return { return {
manual: { type: Boolean }, manual: { type: Boolean },
fileId: { type: String }, sourceId: { type: String },
error: { type: Boolean }, error: { type: Boolean },
reauth: { type: Boolean } reauth: { type: Boolean }
} }
} }
updated(changedProperties) { updated(changedProperties) {
if (changedProperties.has("fileId")) { if (changedProperties.has("sourceId")) {
this.error = false; this.error = false;
//this.scriptLoaded = false; //this.scriptLoaded = false;
this.manual = false; this.manual = false;
@@ -1598,7 +1618,8 @@ class WrGdrive extends LitElement
} }
async authed(response) { async authed(response) {
const fileId = this.fileId; const sourceId = this.sourceId;
const fileId = sourceId.slice("googledrive://".length);
const metadataUrl = `https://www.googleapis.com/drive/v3/files/${fileId}`; const metadataUrl = `https://www.googleapis.com/drive/v3/files/${fileId}`;
const authToken = response.access_token; const authToken = response.access_token;
const headers = {"Authorization": `Bearer ${authToken}`}; const headers = {"Authorization": `Bearer ${authToken}`};
@@ -1614,8 +1635,6 @@ class WrGdrive extends LitElement
this.error = false; this.error = false;
const metadata = await resp.json(); const metadata = await resp.json();
const sourceId = `googledrive://${fileId}`;
const name = metadata.name; const name = metadata.name;
const displayName = `Google Drive file: ` + metadata.name; const displayName = `Google Drive file: ` + metadata.name;
@@ -1636,7 +1655,7 @@ class WrGdrive extends LitElement
` : html` ` : html`
${this.error ? html` ${this.error ? html`
<div class="error has-text-danger"> <div class="error has-text-danger">
<p>${this.reauth ? 'Please reauthorize Google Drive to continue loading.' : <p>${this.reauth ? 'Some resources are loaded on demand from Google Drive, which requires reauthorization.' :
'Could not access this file with the current Google Drive account.'}</p> 'Could not access this file with the current Google Drive account.'}</p>
<p>If you have multiple Google Drive accounts, be sure to select the correct one.</p> <p>If you have multiple Google Drive accounts, be sure to select the correct one.</p>
</div> </div>
+3 -3
View File
File diff suppressed because one or more lines are too long