-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding age gate extension source code for tutorial
- Loading branch information
Showing
17 changed files
with
333 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
const { | ||
OK, | ||
INTERNAL_SERVER_ERROR | ||
} = require('@evershop/evershop/src/lib/util/httpStatus'); | ||
const { getSetting } = require('@evershop/evershop/src/modules/setting/services/setting'); | ||
|
||
// eslint-disable-next-line no-unused-vars | ||
module.exports = async (request, response, delegate, next) => { | ||
const { age } = request.body; | ||
try { | ||
response.status(OK); | ||
const minAge = await getSetting('minAge'); | ||
if (age && age >= minAge) { | ||
// Set the age verified cookie | ||
response.cookie('age-verified', 1, { | ||
maxAge: 1000 * 60 * 60 * 24 * 10 | ||
}); | ||
response.json({ | ||
data: { | ||
age, | ||
passed: true | ||
} | ||
}); | ||
} else { | ||
response.json({ | ||
data: { | ||
age, | ||
passed: false | ||
} | ||
}); | ||
} | ||
} catch (e) { | ||
response.status(INTERNAL_SERVER_ERROR); | ||
response.json({ | ||
error: { | ||
status: INTERNAL_SERVER_ERROR, | ||
message: e.message | ||
} | ||
}); | ||
} | ||
}; |
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,5 @@ | ||
const bodyParser = require('body-parser'); | ||
|
||
module.exports = (request, response, delegate, next) => { | ||
bodyParser.json({ inflate: false })(request, response, next); | ||
}; |
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,11 @@ | ||
{ | ||
"type": "object", | ||
"properties": { | ||
"age": { | ||
"type": ["integer", "string"], | ||
"pattern": "^[0-9]+$" | ||
} | ||
}, | ||
"required": ["age"], | ||
"additionalProperties": true | ||
} |
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,5 @@ | ||
{ | ||
"methods": ["POST"], | ||
"path": "/age-verify", | ||
"access": "public" | ||
} |
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,3 @@ | ||
extend type Setting { | ||
minAge: Int! | ||
} |
12 changes: 12 additions & 0 deletions
12
packages/agegate/graphql/types/AgeSetting/AgeSetting.resolvers.js
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,12 @@ | ||
module.exports = { | ||
Setting: { | ||
minAge: (setting) => { | ||
const minAge = setting.find((s) => s.name === 'minAge'); | ||
if (minAge) { | ||
return minAge.value; | ||
} else { | ||
return 18; | ||
} | ||
} | ||
} | ||
}; |
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,79 @@ | ||
import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import { toast } from 'react-toastify'; | ||
import Area from '@components/common/Area'; | ||
import { Form } from '@components/common/form/Form'; | ||
import SettingMenu from '@components/admin/setting/SettingMenu'; | ||
import { Field } from '@components/common/form/Field'; | ||
import { Card } from '@components/admin/cms/Card'; | ||
|
||
export default function AgeSetting({ saveSettingApi, setting: { minAge } }) { | ||
return ( | ||
<div className="main-content-inner"> | ||
<div className="grid grid-cols-6 gap-x-2 grid-flow-row "> | ||
<div className="col-span-2"> | ||
<SettingMenu /> | ||
</div> | ||
<div className="col-span-4"> | ||
<Form | ||
id="ageSettingForm" | ||
method="POST" | ||
action={saveSettingApi} | ||
onSuccess={(response) => { | ||
if (!response.error) { | ||
toast.success('Setting saved'); | ||
} else { | ||
toast.error(response.error.message); | ||
} | ||
}} | ||
> | ||
<Card title="Age Setting"> | ||
<Card.Session> | ||
<Area | ||
id="ageSetting" | ||
className="grid gap-2" | ||
coreComponents={[ | ||
{ | ||
component: { | ||
default: Field | ||
}, | ||
props: { | ||
name: 'minAge', | ||
placeHolder: 'Minimum Age', | ||
label: 'Minimum Age', | ||
type: 'text', | ||
value: minAge, | ||
validationRules: ['notEmpty'] | ||
} | ||
} | ||
]} | ||
/> | ||
</Card.Session> | ||
</Card> | ||
</Form> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
AgeSetting.propTypes = { | ||
saveSettingApi: PropTypes.string.isRequired, | ||
setting: PropTypes.shape({ | ||
minAge: PropTypes.number.isRequired | ||
}).isRequired | ||
}; | ||
|
||
export const layout = { | ||
areaId: 'content', | ||
sortOrder: 10 | ||
}; | ||
|
||
export const query = ` | ||
query Query { | ||
saveSettingApi: url(routeId: "saveSetting"), | ||
setting { | ||
minAge | ||
} | ||
} | ||
`; |
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,8 @@ | ||
const { setContextValue } = require("@evershop/evershop/src/modules/graphql/services/contextHelper"); | ||
|
||
module.exports = (request) => { | ||
setContextValue(request, 'pageInfo', { | ||
title: 'Age Setting', | ||
description: 'Age Setting' | ||
}); | ||
}; |
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,4 @@ | ||
{ | ||
"methods": ["GET"], | ||
"path": "/setting/agegate" | ||
} |
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,26 @@ | ||
import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import { Card } from '@components/admin/cms/Card'; | ||
|
||
export default function AgeSettingMenu({ ageSettingUrl }) { | ||
return ( | ||
<Card.Session title={<a href={ageSettingUrl}>Age Setting</a>}> | ||
<div>Configure the minimum age to access the site</div> | ||
</Card.Session> | ||
); | ||
} | ||
|
||
AgeSettingMenu.propTypes = { | ||
ageSettingUrl: PropTypes.string.isRequired | ||
}; | ||
|
||
export const layout = { | ||
areaId: 'settingPageMenu', | ||
sortOrder: 50 | ||
}; | ||
|
||
export const query = ` | ||
query Query { | ||
ageSettingUrl: url(routeId: "ageSetting") | ||
} | ||
`; |
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,74 @@ | ||
import { Field } from '@components/common/form/Field'; | ||
import { Form } from '@components/common/form/Form'; | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { toast } from 'react-toastify'; | ||
|
||
function AgeForm({ action, homeUrl, failurePageUrl, setting: { minAge } }) { | ||
return ( | ||
<div className="page-width p-2"> | ||
<Form | ||
id="ageForm" | ||
action={action} | ||
method="POST" | ||
onSuccess={(response) => { | ||
if (!response.error) { | ||
if (response.data.passed) { | ||
window.location.href = homeUrl; | ||
} else { | ||
// Redirect to age verification failure page | ||
window.location.href = failurePageUrl; | ||
} | ||
} else { | ||
toast.error('Something wront. Please try again later'); | ||
} | ||
}} | ||
btnText="Submit" | ||
> | ||
<div className="text-center"> | ||
<h3>Age Verification</h3> | ||
<p> | ||
We only allow users who are {minAge} years and above. Please enter | ||
your age to proceed. | ||
</p> | ||
</div> | ||
<br /> | ||
<div className="form-group"> | ||
<Field | ||
type="text" | ||
name="age" | ||
value={1} | ||
validationRules={['notEmpty']} | ||
/> | ||
</div> | ||
</Form> | ||
</div> | ||
); | ||
} | ||
|
||
AgeForm.propTypes = { | ||
action: PropTypes.string.isRequired, | ||
homeUrl: PropTypes.string.isRequired, | ||
failurePageUrl: PropTypes.string.isRequired, | ||
setting: PropTypes.shape({ | ||
minAge: PropTypes.number.isRequired | ||
}).isRequired | ||
}; | ||
|
||
export const layout = { | ||
areaId: 'content', | ||
sortOrder: 1 | ||
}; | ||
|
||
export const query = ` | ||
query Query { | ||
action: url(routeId: "verifyAge"), | ||
homeUrl: url(routeId: "homepage"), | ||
failurePageUrl: url(routeId: "ageVerifyFailure"), | ||
setting { | ||
minAge | ||
} | ||
} | ||
`; | ||
|
||
export default AgeForm; |
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,8 @@ | ||
const { setContextValue } = require("@evershop/evershop/src/modules/graphql/services/contextHelper"); | ||
|
||
module.exports = (request) => { | ||
setContextValue(request, 'pageInfo', { | ||
title: 'Age Gate', | ||
description: 'Age Gate' | ||
}) | ||
}; |
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,4 @@ | ||
{ | ||
"methods": ["GET"], | ||
"path": "/age-gate" | ||
} |
21 changes: 21 additions & 0 deletions
21
packages/agegate/pages/frontStore/ageVerifyFailure/Index.jsx
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 @@ | ||
import React from 'react'; | ||
|
||
function Index() { | ||
return ( | ||
<div className='page-width p-2'> | ||
<div className='text-center p-2'> | ||
<h3>Sorry!</h3> | ||
<p> | ||
You are not old enough to view this site. Sorry!!! | ||
</p> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export const layout = { | ||
areaId: 'content', | ||
sortOrder: 1 | ||
} | ||
|
||
export default Index; |
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,8 @@ | ||
const { setContextValue } = require("@evershop/evershop/src/modules/graphql/services/contextHelper"); | ||
|
||
module.exports = (request) => { | ||
setContextValue(request, 'pageInfo', { | ||
title: 'Age verification failed', | ||
description: 'Age verification failed' | ||
}); | ||
}; |
4 changes: 4 additions & 0 deletions
4
packages/agegate/pages/frontStore/ageVerifyFailure/route.json
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,4 @@ | ||
{ | ||
"methods": ["GET"], | ||
"path": "/age-verify-failed" | ||
} |
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,20 @@ | ||
const { buildUrl } = require('@evershop/evershop/src/lib/router/buildUrl'); | ||
|
||
module.exports = async (request, response, delegate, next) => { | ||
// Get the age verify cookie | ||
const ageVerifyCookie = request.cookies['age-verified']; | ||
if (!ageVerifyCookie || parseInt(ageVerifyCookie, 10) !== 1) { | ||
// Get the current route | ||
const { currentRoute } = request; | ||
if ( | ||
currentRoute.id === 'ageGate' || | ||
currentRoute.id === 'ageVerifyFailure' | ||
) { | ||
return next(); | ||
} else { | ||
return response.redirect(buildUrl('ageGate')); | ||
} | ||
} else { | ||
return next(); | ||
} | ||
}; |