Родитель
39433db492
Коммит
9c99295e43
22
.mergify.yml
22
.mergify.yml
|
@ -1,3 +1,14 @@
|
||||||
|
queue_rules:
|
||||||
|
- name: dependabot
|
||||||
|
conditions:
|
||||||
|
- "status-success=continuous-integration/travis-ci/pr"
|
||||||
|
- "status-success=continuous-integration/travis-ci/push"
|
||||||
|
|
||||||
|
- name: ready-to-merge
|
||||||
|
conditions:
|
||||||
|
- "status-success=continuous-integration/travis-ci/pr"
|
||||||
|
- "status-success=continuous-integration/travis-ci/push"
|
||||||
|
|
||||||
pull_request_rules:
|
pull_request_rules:
|
||||||
- name: Automatic merge for dependabot PRs
|
- name: Automatic merge for dependabot PRs
|
||||||
conditions:
|
conditions:
|
||||||
|
@ -6,10 +17,10 @@ pull_request_rules:
|
||||||
- "status-success=continuous-integration/travis-ci/pr"
|
- "status-success=continuous-integration/travis-ci/pr"
|
||||||
- "status-success=continuous-integration/travis-ci/push"
|
- "status-success=continuous-integration/travis-ci/push"
|
||||||
actions:
|
actions:
|
||||||
merge:
|
queue:
|
||||||
method: squash
|
method: squash
|
||||||
strict_method: rebase
|
name: dependabot
|
||||||
strict: true
|
|
||||||
- name: Automatic merge for PRs labelled "ready to merge"
|
- name: Automatic merge for PRs labelled "ready to merge"
|
||||||
conditions:
|
conditions:
|
||||||
- "#approved-reviews-by>=1"
|
- "#approved-reviews-by>=1"
|
||||||
|
@ -17,7 +28,6 @@ pull_request_rules:
|
||||||
- "status-success=continuous-integration/travis-ci/push"
|
- "status-success=continuous-integration/travis-ci/push"
|
||||||
- "label=ready-to-merge"
|
- "label=ready-to-merge"
|
||||||
actions:
|
actions:
|
||||||
merge:
|
queue:
|
||||||
method: squash
|
method: squash
|
||||||
strict_method: rebase
|
name: ready-to-merge
|
||||||
strict: true
|
|
||||||
|
|
|
@ -54,6 +54,8 @@ This starts a few image optimization scripts.
|
||||||
`PULSE_API` | Default: `https://pulse-api.mofostaging.net/api/pulse`<br><br>URL to Pulse API. e.g., `http://test.example.com:8000/api/pulse`. <br>To set up a local instance of Pulse API, follow instructions on [Pulse API README doc](https://github.com/mozilla/network-pulse-api/blob/master/README.md).
|
`PULSE_API` | Default: `https://pulse-api.mofostaging.net/api/pulse`<br><br>URL to Pulse API. e.g., `http://test.example.com:8000/api/pulse`. <br>To set up a local instance of Pulse API, follow instructions on [Pulse API README doc](https://github.com/mozilla/network-pulse-api/blob/master/README.md).
|
||||||
`PULSE_LOGIN_URL` | Default: `https://pulse-api.mofostaging.net/accounts/login/`<br><br>URL to use to login to Pulse. This needs to be a Pulse API login url.
|
`PULSE_LOGIN_URL` | Default: `https://pulse-api.mofostaging.net/accounts/login/`<br><br>URL to use to login to Pulse. This needs to be a Pulse API login url.
|
||||||
`PULSE_LOGOUT_URL` | Default: `https://pulse-api.mofostaging.net/accounts/logout/`<br><br>URL to use to logout of Pulse. This needs to be a Pulse API logout url.
|
`PULSE_LOGOUT_URL` | Default: `https://pulse-api.mofostaging.net/accounts/logout/`<br><br>URL to use to logout of Pulse. This needs to be a Pulse API logout url.
|
||||||
|
`USE_RECAPTCHA` | Default: `true`<br><br>Whether or not to have recaptcha securing the sign up/sign in action.
|
||||||
|
`RECAPTCHA_KEY` | Default: empty string<br><br>The recaptcha site key to use, when recaptcha is enabled.
|
||||||
`PROJECT_BATCH_SIZE`| Default: `24`<br><br>Number of projects you want to display as a batch. Make sure this number is divisible by 2 AND 3 so rows display evenly for different screen sizes.
|
`PROJECT_BATCH_SIZE`| Default: `24`<br><br>Number of projects you want to display as a batch. Make sure this number is divisible by 2 AND 3 so rows display evenly for different screen sizes.
|
||||||
`PROFILE_BATCH_SIZE`| Default: `10`<br><br>Number of profiles you want to display as a batch.
|
`PROFILE_BATCH_SIZE`| Default: `10`<br><br>Number of profiles you want to display as a batch.
|
||||||
`LEARN_MORE_LINK` | Default: `https://www.mozillapulse.org/entry/120`<br><br>Link to learn more about what Pulse project is about.
|
`LEARN_MORE_LINK` | Default: `https://www.mozillapulse.org/entry/120`<br><br>Link to learn more about what Pulse project is about.
|
||||||
|
@ -62,6 +64,7 @@ This starts a few image optimization scripts.
|
||||||
`HEROKU_APP_NAME` | Default: `""`<br><br>The name of the review app (generated by Heroku).
|
`HEROKU_APP_NAME` | Default: `""`<br><br>The name of the review app (generated by Heroku).
|
||||||
`GITHUB_TOKEN` | Default: `""`<br><br>GitHub token used by the review app slack webhook.
|
`GITHUB_TOKEN` | Default: `""`<br><br>GitHub token used by the review app slack webhook.
|
||||||
`SLACK_WEBHOOK` | Default: `""`<br><br>Webhook of the Slack channel where the bot is posting.
|
`SLACK_WEBHOOK` | Default: `""`<br><br>Webhook of the Slack channel where the bot is posting.
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
### Staging
|
### Staging
|
||||||
|
|
|
@ -84,12 +84,18 @@ class NavBar extends React.Component {
|
||||||
handleSignInBtnClick(event) {
|
handleSignInBtnClick(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
Analytics.ReactGA.event({
|
try {
|
||||||
category: `Account`,
|
Analytics.ReactGA.event({
|
||||||
action: `Login`,
|
category: `Account`,
|
||||||
label: `Login ${window.location.pathname}`,
|
action: `Login`,
|
||||||
transport: `beacon`,
|
label: `Login ${window.location.pathname}`,
|
||||||
});
|
transport: `beacon`,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
// This does not need to succeed, but we also
|
||||||
|
// don't want a throw to prevent the actual
|
||||||
|
// login from happening.
|
||||||
|
}
|
||||||
|
|
||||||
user.login(utility.getCurrentURL());
|
user.login(utility.getCurrentURL());
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ import env from "./env-client";
|
||||||
import localstorage from "./localstorage.js";
|
import localstorage from "./localstorage.js";
|
||||||
import Service from "./service.js";
|
import Service from "./service.js";
|
||||||
|
|
||||||
|
const useRecaptcha = env.USE_RECAPTCHA;
|
||||||
|
const recaptchaKey = env.RECAPTCHA_KEY;
|
||||||
const loginUrl = env.PULSE_LOGIN_URL;
|
const loginUrl = env.PULSE_LOGIN_URL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,8 +16,11 @@ const Login = {
|
||||||
/*
|
/*
|
||||||
* Generates the oauth url for logging a user in, with a redirect-when-finished URL
|
* Generates the oauth url for logging a user in, with a redirect-when-finished URL
|
||||||
*/
|
*/
|
||||||
getLoginURL(redirectUrl) {
|
getLoginURL(redirectUrl, recaptchaToken) {
|
||||||
return `${loginUrl}?next=${encodeURIComponent(redirectUrl)}`;
|
const trailing = loginUrl.endsWith(`/`) ? `` : `/`;
|
||||||
|
const next = `?next=${encodeURIComponent(redirectUrl)}`;
|
||||||
|
const token = recaptchaToken ? `&token=${recaptchaToken}` : ``;
|
||||||
|
return [loginUrl, trailing, next, token].join(``);
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -113,13 +118,23 @@ class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
login(redirectUrl) {
|
login(redirectUrl) {
|
||||||
// we record that the user started a login in localStorage,
|
const performLogin = (token) => {
|
||||||
// then the app gets closed and oauth happens. Once the
|
// we record that the user started a login in localStorage,
|
||||||
// oauth callback drops the user back at a URL that loads
|
// then the app gets closed and oauth happens. Once the
|
||||||
// the app again, pages can run `user.verify` to finalise
|
// oauth callback drops the user back at a URL that loads
|
||||||
// the login process.
|
// the app again, pages can run `user.verify` to finalise
|
||||||
localstorage.setItem(`pulse:user:attemptingLogin`, `True`);
|
// the login process.
|
||||||
window.location = Login.getLoginURL(redirectUrl);
|
localstorage.setItem(`pulse:user:attemptingLogin`, `True`);
|
||||||
|
window.location = Login.getLoginURL(redirectUrl, token);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (useRecaptcha) {
|
||||||
|
grecaptcha.ready(() =>
|
||||||
|
grecaptcha
|
||||||
|
.execute(recaptchaKey, { action: "submit" })
|
||||||
|
.then((recaptcha_response) => performLogin(recaptcha_response))
|
||||||
|
);
|
||||||
|
} else performLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(location, history) {
|
verify(location, history) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import dotenv from "dotenv";
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
// load default.env so that anything didn't get set in .env or the host environment will get a default value
|
// load default.env so that anything didn't get set in .env or the host environment will get a default value
|
||||||
dotenv.config({ path: `config/default.env` });
|
dotenv.config({ path: `./config/default.env` });
|
||||||
|
|
||||||
let envUtilities = {
|
let envUtilities = {
|
||||||
serializeSafeEnvAsJSON: () => {
|
serializeSafeEnvAsJSON: () => {
|
||||||
|
@ -24,6 +24,8 @@ let envUtilities = {
|
||||||
PULSE_API: process.env.PULSE_API,
|
PULSE_API: process.env.PULSE_API,
|
||||||
PULSE_LOGIN_URL: process.env.PULSE_LOGIN_URL,
|
PULSE_LOGIN_URL: process.env.PULSE_LOGIN_URL,
|
||||||
PULSE_LOGOUT_URL: process.env.PULSE_LOGOUT_URL,
|
PULSE_LOGOUT_URL: process.env.PULSE_LOGOUT_URL,
|
||||||
|
USE_RECAPTCHA: process.env.USE_RECAPTCHA,
|
||||||
|
RECAPTCHA_KEY: process.env.RECAPTCHA_KEY,
|
||||||
};
|
};
|
||||||
|
|
||||||
return JSON.stringify(config);
|
return JSON.stringify(config);
|
||||||
|
|
|
@ -10,12 +10,15 @@ export default {
|
||||||
`https://platform.twitter.com/widgets.js`,
|
`https://platform.twitter.com/widgets.js`,
|
||||||
`https://www.googletagmanager.com/gtm.js`,
|
`https://www.googletagmanager.com/gtm.js`,
|
||||||
`https://www.googletagmanager.com/debug/bootstrap`,
|
`https://www.googletagmanager.com/debug/bootstrap`,
|
||||||
|
`https://www.google.com/recaptcha/api.js`,
|
||||||
|
`https://www.gstatic.com/recaptcha/releases/`,
|
||||||
],
|
],
|
||||||
fontSrc: [
|
fontSrc: [
|
||||||
`'self'`,
|
`'self'`,
|
||||||
`https://code.cdn.mozilla.net`,
|
`https://code.cdn.mozilla.net`,
|
||||||
`https://fonts.gstatic.com`,
|
`https://fonts.gstatic.com`,
|
||||||
],
|
],
|
||||||
|
frameSrc: [`https://www.google.com/`],
|
||||||
styleSrc: [
|
styleSrc: [
|
||||||
`'self'`,
|
`'self'`,
|
||||||
`'unsafe-inline'`,
|
`'unsafe-inline'`,
|
||||||
|
@ -28,6 +31,8 @@ export default {
|
||||||
url.parse(env.PULSE_API).host ||
|
url.parse(env.PULSE_API).host ||
|
||||||
`https://network-pulse-api-staging.herokuapp.com/`,
|
`https://network-pulse-api-staging.herokuapp.com/`,
|
||||||
`https://www.mozilla.org/en-US/newsletter/`,
|
`https://www.mozilla.org/en-US/newsletter/`,
|
||||||
|
`https://www.google.com/recaptcha/api.js`,
|
||||||
|
`https://www.gstatic.com/recaptcha/releases/`,
|
||||||
],
|
],
|
||||||
childSrc: [
|
childSrc: [
|
||||||
`https://syndication.twitter.com`,
|
`https://syndication.twitter.com`,
|
||||||
|
|
|
@ -137,6 +137,11 @@ function renderPage(appHtml, reactHelmet, canonicalUrl) {
|
||||||
? `<meta name="googlebot" content="noindex, nofollow, noarchive" />`
|
? `<meta name="googlebot" content="noindex, nofollow, noarchive" />`
|
||||||
: ``;
|
: ``;
|
||||||
|
|
||||||
|
let recaptcha = ``;
|
||||||
|
if (env.USE_RECAPTCHA) {
|
||||||
|
recaptcha = `<script src="https://www.google.com/recaptcha/api.js?render=${env.RECAPTCHA_KEY}" async></script>`;
|
||||||
|
}
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
|
@ -148,7 +153,7 @@ function renderPage(appHtml, reactHelmet, canonicalUrl) {
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
${twitterCard}
|
${twitterCard}
|
||||||
${ogTags}
|
${ogTags}
|
||||||
<script type="text/javascript" async src="https://platform.twitter.com/widgets.js"></script>
|
<script src="https://platform.twitter.com/widgets.js" async defer></script>
|
||||||
<link rel="apple-touch-icon" type="image/png" sizes="180x180" href="/assets/favicons/apple-touch-icon-180x180@2x.png">
|
<link rel="apple-touch-icon" type="image/png" sizes="180x180" href="/assets/favicons/apple-touch-icon-180x180@2x.png">
|
||||||
<link rel="icon" type="image/png" sizes="196x196" href="/assets/favicons/favicon-196x196@2x.png">
|
<link rel="icon" type="image/png" sizes="196x196" href="/assets/favicons/favicon-196x196@2x.png">
|
||||||
<link rel="shortcut icon" href="/assets/favicons/favicon.ico">
|
<link rel="shortcut icon" href="/assets/favicons/favicon.ico">
|
||||||
|
@ -164,6 +169,7 @@ function renderPage(appHtml, reactHelmet, canonicalUrl) {
|
||||||
${reactHelmet.title.toString()}
|
${reactHelmet.title.toString()}
|
||||||
<meta name="ga-identifier" content="UA-87658599-4">
|
<meta name="ga-identifier" content="UA-87658599-4">
|
||||||
<meta name="gtm-identifier" content="GTM-KHLX47C">
|
<meta name="gtm-identifier" content="GTM-KHLX47C">
|
||||||
|
${recaptcha}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">${appHtml}</div>
|
<div id="app">${appHtml}</div>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче