-
Notifications
You must be signed in to change notification settings - Fork 288
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #667 from janus-reith/storefront-v2
Storefront v2
- Loading branch information
Showing
438 changed files
with
8,043 additions
and
17,737 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
CANONICAL_URL=http://localhost:4000 | ||
ENABLE_SPA_ROUTING=true | ||
BUILD_GRAPHQL_URL=http://localhost:3000/graphql | ||
EXTERNAL_GRAPHQL_URL=http://localhost:3000/graphql | ||
INTERNAL_GRAPHQL_URL=http://api.reaction.localhost:3000/graphql | ||
OAUTH2_ADMIN_PORT=4445 | ||
OAUTH2_ADMIN_URL=http://hydra.reaction.localhost:4445 | ||
OAUTH2_AUTH_URL=http://localhost:4444/oauth2/auth | ||
OAUTH2_CLIENT_ID=example-storefront | ||
OAUTH2_CLIENT_SECRET=CHANGEME | ||
OAUTH2_PUBLIC_LOGOUT_URL=http://localhost:4444/oauth2/sessions/logout | ||
OAUTH2_HOST=hydra.reaction.localhost | ||
OAUTH2_IDP_PUBLIC_CHANGE_PASSWORD_URL=http://localhost:4100/account/change-password?email=EMAIL&from=FROM | ||
OAUTH2_IDP_HOST_URL=http://identity.reaction.localhost:4100 | ||
OAUTH2_TOKEN_URL=http://hydra.reaction.localhost:4444/oauth2/token | ||
PORT=4000 | ||
SEGMENT_ANALYTICS_SKIP_MINIMIZE=true | ||
SEGMENT_ANALYTICS_WRITE_KEY=ENTER_KEY_HERE | ||
SESSION_MAX_AGE_MS=2592000000 | ||
SESSION_SECRET=CHANGEME | ||
STRIPE_PUBLIC_API_KEY=ENTER_STRIPE_PUBLIC_KEY_HERE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
.c9 | ||
.env* | ||
!.env.example* | ||
!.env.prod* | ||
*.csv | ||
*.dat | ||
*.gz | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
export default function headerLookup(req) { | ||
let found; | ||
|
||
if (typeof req !== "undefined") { | ||
const { headers } = req; | ||
if (!headers) return found; | ||
|
||
const locales = []; | ||
const acceptLanguage = headers["accept-language"]; | ||
|
||
if (acceptLanguage) { | ||
const lngs = []; let i; let m; | ||
const rgx = /(([a-z]{2})-?([A-Z]{2})?)\s*;?\s*(q=([0-9.]+))?/gi; | ||
|
||
do { | ||
m = rgx.exec(acceptLanguage); | ||
if (m) { | ||
const lng = m[1]; const weight = m[5] || "1"; const q = Number(weight); | ||
if (lng && !isNaN(q)) { | ||
lngs.push({ lng, q }); | ||
} | ||
} | ||
} while (m); | ||
|
||
lngs.sort((a, b) => b.q - a.q); | ||
|
||
for (i = 0; i < lngs.length; i++) { | ||
locales.push(lngs[i].lng); | ||
} | ||
|
||
if (locales.length) found = locales; | ||
} | ||
} | ||
|
||
return found; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import headerLanguage from "./headerLanguage"; | ||
import redirect from "./redirect"; | ||
|
||
export default (req, res) => { | ||
const { | ||
query: { slug }, | ||
_parsedUrl | ||
} = req; | ||
|
||
const fallback = "de"; | ||
const allowedLocales = [ | ||
{ name: "de-DE", locale: "de" }, | ||
{ name: "de", locale: "de" }, | ||
{ name: "en-AU", locale: "en" }, | ||
{ name: "en-IN", locale: "en" }, | ||
{ name: "en-CA", locale: "en" }, | ||
{ name: "en-NZ", locale: "en" }, | ||
{ name: "en-US", locale: "en" }, | ||
{ name: "en-ZA", locale: "en" }, | ||
{ name: "en-GB", locale: "en" }, | ||
{ name: "en", locale: "en" } | ||
]; | ||
|
||
const detections = headerLanguage(req); | ||
|
||
let found; | ||
|
||
if (detections && detections.length) { | ||
detections.forEach((language) => { | ||
if (found || typeof language !== "string") return; | ||
|
||
const lookedUpLocale = allowedLocales.find((allowedLocale) => allowedLocale.name === language); | ||
|
||
if (lookedUpLocale) { | ||
found = lookedUpLocale.locale; | ||
} | ||
}); | ||
} | ||
|
||
if (!found) { | ||
found = fallback; | ||
} | ||
|
||
const queryPart = (_parsedUrl && _parsedUrl.query) ? `?${_parsedUrl.query}` : ""; | ||
|
||
if (slug) { | ||
return redirect(res, 302, `/${found}${slug ? `/${slug.join("/")}` : ""}${queryPart}`); | ||
} | ||
|
||
return redirect(res, 302, `/${found}${queryPart}`); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import OAuth2Strategy from "passport-oauth2"; | ||
import passport from "passport"; | ||
import sessions from "client-sessions"; | ||
import appConfig from "../config.js"; | ||
import redirect from "./redirect"; | ||
|
||
export { default as passport } from "passport"; | ||
|
||
let baseUrl = appConfig.CANONICAL_URL; | ||
if (!baseUrl.endsWith("/")) baseUrl = `${baseUrl}/`; | ||
|
||
const oauthRedirectUrl = `${baseUrl}callback`; | ||
|
||
// This is needed to allow custom parameters (e.g. loginActions) to be included | ||
// when requesting authorization. This is setup to allow only loginAction to pass through | ||
OAuth2Strategy.prototype.authorizationParams = function (options = {}) { | ||
return { loginAction: options.loginAction }; | ||
}; | ||
|
||
passport.use("oauth2", new OAuth2Strategy({ | ||
authorizationURL: appConfig.OAUTH2_AUTH_URL, | ||
tokenURL: appConfig.OAUTH2_TOKEN_URL, | ||
clientID: appConfig.OAUTH2_CLIENT_ID, | ||
clientSecret: appConfig.OAUTH2_CLIENT_SECRET, | ||
callbackURL: oauthRedirectUrl, | ||
state: true, | ||
scope: ["offline", "openid"] | ||
}, (accessToken, refreshToken, params, profile, cb) => { | ||
cb(null, { accessToken, refreshToken, idToken: params.id_token }); | ||
})); | ||
|
||
passport.serializeUser((user, done) => { | ||
done(null, JSON.stringify(user)); | ||
}); | ||
|
||
passport.deserializeUser((user, done) => { | ||
done(null, JSON.parse(user)); | ||
}); | ||
|
||
export default (handler) => (req, res) => { | ||
if (!res.redirect) { | ||
res.redirect = (location) => redirect(res, 302, location); | ||
} | ||
|
||
sessions({ | ||
cookieName: "session", // This name is required so passport picks it up correctly | ||
secret: appConfig.SESSION_SECRET, | ||
duration: appConfig.SESSION_MAX_AGE_MS | ||
})(req, res, () => | ||
passport.initialize()(req, res, () => | ||
passport.session()(req, res, () => | ||
handler(req, res)))); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export default function redirect(res, statusCode, location) { | ||
if (!res) { | ||
throw new Error("Response object required"); | ||
} | ||
|
||
if (!statusCode) { | ||
throw new Error("Status code required"); | ||
} | ||
|
||
if (!location) { | ||
throw new Error("Location required"); | ||
} | ||
|
||
res.statusCode = statusCode; | ||
res.setHeader("Location", location); | ||
res.end(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import React, { useState, Fragment } from "react"; | ||
import inject from "hocs/inject"; | ||
import { makeStyles } from "@material-ui/core/styles"; | ||
import IconButton from "@material-ui/core/IconButton"; | ||
import Button from "@material-ui/core/Button"; | ||
import ButtonBase from "@material-ui/core/ButtonBase"; | ||
import AccountIcon from "mdi-material-ui/Account"; | ||
import Popover from "@material-ui/core/Popover"; | ||
import useViewer from "hooks/viewer/useViewer"; | ||
import ViewerInfo from "@reactioncommerce/components/ViewerInfo/v1"; | ||
import Link from "components/Link"; | ||
|
||
const useStyles = makeStyles((theme) => ({ | ||
accountDropdown: { | ||
width: 320, | ||
padding: theme.spacing(2) | ||
}, | ||
marginBottom: { | ||
marginBottom: theme.spacing(2) | ||
} | ||
})); | ||
|
||
const AccountDropdown = () => { | ||
const classes = useStyles(); | ||
const [anchorElement, setAnchorElement] = useState(null); | ||
const [viewer, isLoadingViewer] = useViewer(); | ||
const isAuthenticated = viewer && viewer._id; | ||
|
||
const toggleOpen = (event) => { | ||
setAnchorElement(event.currentTarget); | ||
}; | ||
|
||
const onClose = () => { | ||
setAnchorElement(null); | ||
}; | ||
|
||
return ( | ||
<Fragment> | ||
{ isAuthenticated ? | ||
<ButtonBase onClick={toggleOpen}> | ||
<ViewerInfo viewer={viewer} /> | ||
</ButtonBase> | ||
: | ||
<IconButton color="inherit" onClick={toggleOpen}> | ||
<AccountIcon /> | ||
</IconButton> | ||
} | ||
|
||
<Popover | ||
anchorEl={anchorElement} | ||
anchorOrigin={{ | ||
vertical: "bottom", | ||
horizontal: "center" | ||
}} | ||
open={Boolean(anchorElement)} | ||
onClose={onClose} | ||
> | ||
<div className={classes.accountDropdown}> | ||
{isAuthenticated ? | ||
<Fragment> | ||
<div className={classes.marginBottom}> | ||
<Link href="/profile/address"> | ||
<Button color="primary" fullWidth> | ||
Profile | ||
</Button> | ||
</Link> | ||
</div> | ||
<div className={classes.marginBottom}> | ||
<Button color="primary" fullWidth href={`/change-password?email=${encodeURIComponent(viewer.emailRecords[0].address)}`}> | ||
Change Password | ||
</Button> | ||
</div> | ||
<Button color="primary" fullWidth href="/logout" variant="contained"> | ||
Sign Out | ||
</Button> | ||
</Fragment> | ||
: | ||
<Fragment> | ||
<div className={classes.authContent}> | ||
<Button color="primary" fullWidth href="/signin" variant="contained"> | ||
Sign In | ||
</Button> | ||
</div> | ||
<Button color="primary" fullWidth href="/signup"> | ||
Create Account | ||
</Button> | ||
</Fragment> | ||
} | ||
</div> | ||
</Popover> | ||
</Fragment> | ||
); | ||
}; | ||
|
||
export default inject("authStore")(AccountDropdown); |
File renamed without changes.
Oops, something went wrong.