Skip to content

Commit

Permalink
WIP: Scan for exposures without logging in
Browse files Browse the repository at this point in the history
  • Loading branch information
Vinnl committed Apr 3, 2023
1 parent cb02c0f commit 13d44ab
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 11 deletions.
16 changes: 16 additions & 0 deletions src/client/css/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* These styles are taken from
* https://react-spectrum.adobe.com/react-aria/VisuallyHidden.html,
* and are intended for content that's only relevant to screen reader users. */
.visually-hidden {
border: 0;
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
margin: 0 -1px -1px 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
white-space: nowrap;
}

* {
margin: 0;
padding: 0;
Expand Down
14 changes: 14 additions & 0 deletions src/client/css/partials/landing.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@
display: block;
}

.hero form.exposure-scan {
display: flex;
flex-direction: column;
align-items: start;
gap: var(--padding-md);
}

.hero form.exposure-scan input[type='email'] {
width: 100%;
padding: var(--padding-sm) var(--padding-md);
border-radius: var(--border-radius);
border: 1px solid var(--gray-30);
}

.why-use-monitor > h2,
.why-use-monitor > p {
text-align: center;
Expand Down
21 changes: 21 additions & 0 deletions src/controllers/exposureScan.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { guestLayout } from '../views/guestLayout.js'
import { exposureScan } from '../views/partials/exposureScan.js'

function exposureScanPage (req, res, next) {
if (req.method !== 'POST') {
return next()
}

const data = {
partial: exposureScan,
nonce: res.locals.nonce
}

res.send(guestLayout(data))
}

export { exposureScanPage }
6 changes: 5 additions & 1 deletion src/controllers/landing.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { getCountryCode } from '../utils/country-code.js'
import { guestLayout } from '../views/guestLayout.js'
import { generateToken } from '../utils/csrf.js'
import { landing } from '../views/partials/landing.js'

function landingPage (req, res) {
const data = {
partial: landing,
nonce: res.locals.nonce
nonce: res.locals.nonce,
csrfToken: generateToken(res),
countryCode: getCountryCode(req)
}

res.send(guestLayout(data))
Expand Down
2 changes: 2 additions & 0 deletions src/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ import breachDetailsRoutes from './breach-details.js'

import { dialog } from '../controllers/dialog.js'
import { landingPage } from '../controllers/landing.js'
import { exposureScanPage } from '../controllers/exposureScan.js'
import { notFoundPage } from '../controllers/notFound.js'
import { notFound } from '../middleware/error.js'

const router = express.Router()

router.get('/', landingPage)
router.get('/scan', exposureScanPage)
router.get('*/dialog/:name', dialog)

router.use('/', dockerFlowRoutes)
Expand Down
17 changes: 17 additions & 0 deletions src/utils/fluent.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,23 @@ async function initFluentBundles () {

await Promise.allSettled(promises)

// Fluent files in this directory are not currently localized, but might be
// moved to `/locales/` later to submit them for localization:
const unlocalizedDirname = resolve('../unlocalized/en')

try {
const filenames = readdirSync(unlocalizedDirname).filter(item => item.endsWith('.ftl'))

await Promise.all(filenames.map(async filename => {
const str = await readFile(join(unlocalizedDirname, filename), 'utf8')

fluentBundles.en.addResource(new FluentResource(str))
}))
} catch (e) {
console.error('Could not read Fluent file:', e)
throw new Error(e)
}

console.log('Fluent bundles created:', Object.keys(fluentBundles))
}

Expand Down
9 changes: 9 additions & 0 deletions src/views/partials/exposureScan.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { getMessage } from '../../utils/fluent.js'

export const exposureScan = data => `
Wow such exposure
`
58 changes: 48 additions & 10 deletions src/views/partials/landing.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,7 @@
import { getMessage } from '../../utils/fluent.js'

export const landing = data => `
<section class='hero'>
<div>
<h1>${getMessage('find-out-if-breached')}</h1>
<p>${getMessage('stay-safe-with-tool')}</p>
<a class='button primary' data-cta-id='landing-1' href='/user/breaches'>${getMessage('get-started')}</a>
</div>
<figure>
<img srcset='images/landing-hero.webp 530w, images/landing-hero@2x.webp 1059w' width='530' height='406' alt=''>
</figure>
</section>
${hero(data)}
<section class='why-use-monitor'>
<h2>${getMessage('why-use-monitor')}</h2>
<p>${getMessage('identifying-breaches')}</p>
Expand Down Expand Up @@ -89,3 +80,50 @@ export const landing = data => `
<a class='button primary' data-cta-id='landing-2' href='/user/breaches'>${getMessage('get-started')}</a>
</section>
`

const hero = data => data.countryCode === 'us' ? usHero(data) : defaultHero(data)

const defaultHero = data => `
<section class='hero'>
<div>
<h1>${getMessage('find-out-if-breached')}</h1>
<p>${getMessage('stay-safe-with-tool')}</p>
<a class='button primary' data-cta-id='landing-1' href='/user/breaches'>${getMessage('get-started')}</a>
</div>
<figure>
<img srcset='images/landing-hero.webp 530w, images/landing-hero@2x.webp 1059w' width='530' height='406' alt=''>
</figure>
</section>
`

const usHero = data => `
<section class='hero'>
<div>
<h1>${getMessage('exposure-landing-hero-heading')}</h1>
<p>${getMessage('exposure-landing-hero-lead')}</p>
<form method="POST" action="/scan/" class="exposure-scan">
<input type='hidden' name='csrf-token' value='${data.csrfToken}'>
<label for="scsan_email_adddress" class="visually-hidden">
${getMessage('exposure-landing-hero-email-label')}
</label>
<input
id="scan_email_address"
name="email"
type="email"
placeholder="${getMessage('exposure-landing-hero-email-placeholder')}"
required
/>
<button
type="submit"
class='button primary'
data-cta-id='exposure-landing-1'
>
${getMessage('exposure-landing-hero-cta-label')}
</button>
</form>
</div>
<figure>
<img srcset='images/landing-hero.webp 530w, images/landing-hero@2x.webp 1059w' width='530' height='406' alt=''>
</figure>
</section>
`
5 changes: 5 additions & 0 deletions unlocalized/en/exposure-removal.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
exposure-landing-hero-heading = Find out if your personal information has been compromised
exposure-landing-hero-lead = Stay safe with privacy tools from the makers of Firefox that protect you from hackers and companies that publish and sell your personal information. We’ll alert you of any known data breaches, find and remove your exposed info and continually watch for new exposures.
exposure-landing-hero-email-label = Email address
exposure-landing-hero-email-placeholder = Enter email address
exposure-landing-hero-cta-label = Check for breaches

0 comments on commit 13d44ab

Please sign in to comment.