Skip to content

Commit

Permalink
Add page localization (parse-community#7128)
Browse files Browse the repository at this point in the history
* added localized pages; added refactored page templates; adapted test cases; introduced localization test cases

* added changelog entry

* fixed test description typo

* fixed bug in PromiseRouter where headers are not added for text reponse

* added page parameters in page headers for programmatic use

* refactored tests for PublicAPIRouter

* added mustache lib for template rendering

* fixed fs.promises module reference

* fixed template placeholder typo

* changed redirect response to provide headers instead of query parameters

* fix lint

* fixed syntax errors and typos in html templates

* removed obsolete URI encoding

* added locale inferring from request body and header

* added end-to-end localizaton test

* added server option validation; refactored pages server option

* fixed invalid redirect URL for no locale matching file

* added end-to-end localizaton tests

* adapted tests to new response content

* re-added PublicAPIRouter; added PagesRouter as experimental feature

* refactored PagesRouter test structure

* added configuration option for custom path to pages

* added configuration option for custom endpoint to pages

* fixed lint

* added tests

* added a distinct page for invalid password reset link

* renamed generic page invalidLink to expiredVerificationLink

* improved HTML files documentation

* improved HTML files documentation

* changed changelog entry for experimental feature

* improved file naming to make it more descriptive

* fixed file naming and env parameter naming

* added readme entry

* fixed readme TOC - hasn't been updated in a while

* added localization with JSON resource

* added JSON localization to feature pages (password reset, email verification)

* updated readme

* updated readme

* optimized JSON localization for feature pages; added e2e test case

* fixed readme typo

* minor refactoring of existing tests

* fixed bug where Object type was not recognized as config key type

* added feature config placeholders

* prettier

* added passing locale to page config placeholder callback

* refactored passing locale to placeholder to pass test

* added config placeholder feature to README

* fixed typo in README
  • Loading branch information
mtrezza authored Feb 9, 2021
1 parent e3ed6e4 commit 7f47b04
Show file tree
Hide file tree
Showing 41 changed files with 4,332 additions and 2,900 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
__BREAKING CHANGES:__
- NEW: Added file upload restriction. File upload is now only allowed for authenticated users by default for improved security. To allow file upload also for Anonymous Users or Public, set the `fileUpload` parameter in the [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html). [#7071](https://github.com/parse-community/parse-server/pull/7071). Thanks to [dblythy](https://github.com/dblythy), [Manuel Trezza](https://github.com/mtrezza).
___
- NEW: Added convenience method Parse.Cloud.sendEmail(...) to send email via email adapter in Cloud Code. [#7089](https://github.com/parse-community/parse-server/pull/7089). Thanks to [dblythy](https://github.com/dblythy)
- NEW (EXPERIMENTAL): Added new page router with placeholder rendering and localization of custom and feature pages such as password reset and email verification. **Caution, this is an experimental feature that may not be appropriate for production.** [#6891](https://github.com/parse-community/parse-server/issues/6891). Thanks to [Manuel Trezza](https://github.com/mtrezza).
- NEW: Added convenience method `Parse.Cloud.sendEmail(...)` to send email via email adapter in Cloud Code. [#7089](https://github.com/parse-community/parse-server/pull/7089). Thanks to [dblythy](https://github.com/dblythy)
- NEW: LiveQuery support for $and, $nor, $containedBy, $geoWithin, $geoIntersects queries [#7113](https://github.com/parse-community/parse-server/pull/7113). Thanks to [dplewis](https://github.com/dplewis)
- NEW: Supporting patterns in LiveQuery server's config parameter `classNames` [#7131](https://github.com/parse-community/parse-server/pull/7131). Thanks to [Nes-si](https://github.com/Nes-si)
- IMPROVE: Added new account lockout policy option `accountLockout.unlockOnPasswordReset` to automatically unlock account on password reset. [#7146](https://github.com/parse-community/parse-server/pull/7146). Thanks to [Manuel Trezza](https://github.com/mtrezza).
Expand Down
301 changes: 256 additions & 45 deletions README.md

Large diffs are not rendered by default.

4,124 changes: 1,286 additions & 2,838 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"lru-cache": "5.1.1",
"mime": "2.5.0",
"mongodb": "3.6.3",
"mustache": "4.1.0",
"parse": "2.19.0",
"pg-promise": "10.9.1",
"pluralize": "8.0.0",
Expand Down
17 changes: 17 additions & 0 deletions public/custom_json.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<!--
This page demonstrates how to localize using a JSON file that contains the
translations for each placeholder.
-->
<html>

<head>
<title>{{title}}</title>
</head>

<body>
<h1>{{heading}}</h1>
<p>{{body}}</p>
</body>

</html>
23 changes: 23 additions & 0 deletions public/custom_json.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"en": {
"translation": {
"title": "Hello!",
"heading": "Welcome to {{appName}}!",
"body": "We are delighted to welcome you on board."
}
},
"de": {
"translation": {
"title": "Hallo!",
"heading": "Willkommen bei {{appName}}!",
"body": "Wir freuen uns, dich begrüßen zu dürfen."
}
},
"de-AT": {
"translation": {
"title": "Servus!",
"heading": "Willkommen bei {{appName}}!",
"body": "Wir freuen uns, dich begrüßen zu dürfen."
}
}
}
24 changes: 24 additions & 0 deletions public/de-AT/email_verification_link_expired.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a verify email link with a security
token that is expired or incorrect. This can either mean the user has clicked
on a stale link (i.e. re-clicked on the link) or this could be a sign of a
malicious user trying to tamper with your app.
-->
<html>

<head>
<title>Email Verification</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Expired verification link!</h1>
<form method="POST" action="{{{publicServerUrl}}}/apps/{{{appId}}}/resend_verification_email">
<input name="username" type="hidden" value="{{{username}}}">
<input name="locale" type="hidden" value="{{{locale}}}">
<button type="submit">Resend Link</button>
</form>
</body>

</html>
21 changes: 21 additions & 0 deletions public/de-AT/email_verification_link_invalid.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a verify email link with parameters
that are missing or incorrect. This can either mean the user has incorrectly
entered a link or this could be a sign of a malicious user trying to tamper
with your app.
If the link contains an expired security token (or the email has already
been verified), this page is not displayed, there is another page for that.
-->
<html>

<head>
<title>Email Verification</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Invalid verification link!</h1>
</body>

</html>
21 changes: 21 additions & 0 deletions public/de-AT/email_verification_send_fail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a verify email link with a security
token that is expired or incorrect, then requests to receive another link,
but it fails because the username is invalid or the email has already been
verified. This can either mean the user has previously verified the email
or this could be a sign of a malicious user trying to tamper with your app.
-->
<html>

<head>
<title>Email Verification</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Invalid link!</h1>
<p>No link sent. User not found or email already verified.</p>
</body>

</html>
19 changes: 19 additions & 0 deletions public/de-AT/email_verification_send_success.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a verify email link with a
security token that is expired, then requests to receive another email
with a new link and the email is sent successfully.
-->
<html>

<head>
<title>Email Verification</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Link sent!</h1>
<p>A new link has been sent. Check your email.</p>
</body>

</html>
18 changes: 18 additions & 0 deletions public/de-AT/email_verification_success.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a verify email link and the
email gets verified successfully.
-->
<html>

<head>
<title>Email Verification</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Email verified!</h1>
<p>Successfully verified your email for account: {{username}}.</p>
</body>

</html>
65 changes: 65 additions & 0 deletions public/de-AT/password_reset.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<!DOCTYPE html>
<!--
This page is displayed when someone clicks a valid 'reset password' link.
Users should feel free to add to this page (i.e. branding or security widgets)
but should be sure not to delete any of the form inputs or the javascript from the
template file. This javascript is what adds the necessary values to authenticate
this session with Parse.
The query params 'username' and 'app' hold the friendly names for your current user and
your app. You should feel free to incorporate their values to make the page more personal.
If you are missing form parameters in your POST, Parse will navigate back to this page and
add an 'error' query parameter.
-->
<html>

<head>
<title>Password Reset</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Reset Your Password</h1>
<noscript><p>We apologize, but resetting your password requires javascript</p></noscript>
<p>You can set a new Password for your account: {{username}}</p>
<br />
<p>{{error}}</p>
<form id='form' action='{{{publicServerUrl}}}/apps/{{{appId}}}/request_password_reset' method='POST'>
<input name='utf-8' type='hidden' value='' />
<input name="username" type="hidden" id="username" value="{{{username}}}" />
<input name="token" type="hidden" id="token" value="{{{token}}}" />
<input name="locale" type="hidden" id="locale" value="{{{locale}}}" />

<p>New Password</p>
<input name="new_password" type="password" id="password" />
<p>Confirm New Password</p>
<input name="confirm_new_password" type="password" id="password_confirm" />
<br />
<p id="password_match_info"></p>
<br />
<button id="change_password">Change Password</button>
</form>

<script>
window.onload = function() {
document.getElementById("password").oninput = validatePassword;
document.getElementById("password_confirm").oninput = validatePassword;
document.getElementById("change_password").disabled = true;

function validatePassword() {
var pass2 = document.getElementById("password").value;
var pass1 = document.getElementById("password_confirm").value;
if(pass1 !== pass2) {
if(document.getElementById("password_confirm").value) {
document.getElementById("change_password").disabled = true;
document.getElementById("password_match_info").innerHTML = "Must match the previous entry";
}
} else {
document.getElementById("change_password").disabled = false;
document.getElementById("password_match_info").innerHTML = "";
}
}
}
</script>
</body>

</html>
19 changes: 19 additions & 0 deletions public/de-AT/password_reset_link_invalid.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a password reset link with parameters
that are missing or incorrect. This can either mean the user has incorrectly
entered a link or this could be a sign of a malicious user trying to tamper
with your app.
-->
<html>

<head>
<title>Password Reset</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Invalid password reset link!</h1>
</body>

</html>
18 changes: 18 additions & 0 deletions public/de-AT/password_reset_success.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a reset password link, then submits
the form with a new password and the password gets updated successfully.
-->
<html>

<head>
<title>Password Reset</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Success!</h1>
<p>Your password has been updated.</p>
</body>

</html>
24 changes: 24 additions & 0 deletions public/de/email_verification_link_expired.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a verify email link with a security
token that is expired or incorrect. This can either mean the user has clicked
on a stale link (i.e. re-clicked on the link) or this could be a sign of a
malicious user trying to tamper with your app.
-->
<html>

<head>
<title>Email Verification</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Expired verification link!</h1>
<form method="POST" action="{{{publicServerUrl}}}/apps/{{{appId}}}/resend_verification_email">
<input name="username" type="hidden" value="{{{username}}}">
<input name="locale" type="hidden" value="{{{locale}}}">
<button type="submit">Resend Link</button>
</form>
</body>

</html>
21 changes: 21 additions & 0 deletions public/de/email_verification_link_invalid.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a verify email link with parameters
that are missing or incorrect. This can either mean the user has incorrectly
entered a link or this could be a sign of a malicious user trying to tamper
with your app.
If the link contains an expired security token (or the email has already
been verified), this page is not displayed, there is another page for that.
-->
<html>

<head>
<title>Email Verification</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Invalid verification link!</h1>
</body>

</html>
21 changes: 21 additions & 0 deletions public/de/email_verification_send_fail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a verify email link with a security
token that is expired or incorrect, then requests to receive another link,
but it fails because the username is invalid or the email has already been
verified. This can either mean the user has previously verified the email
or this could be a sign of a malicious user trying to tamper with your app.
-->
<html>

<head>
<title>Email Verification</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Invalid link!</h1>
<p>No link sent. User not found or email already verified.</p>
</body>

</html>
19 changes: 19 additions & 0 deletions public/de/email_verification_send_success.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a verify email link with a
security token that is expired, then requests to receive another email
with a new link and the email is sent successfully.
-->
<html>

<head>
<title>Email Verification</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Link sent!</h1>
<p>A new link has been sent. Check your email.</p>
</body>

</html>
18 changes: 18 additions & 0 deletions public/de/email_verification_success.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<!--
This page is displayed when a user opens a verify email link and the
email gets verified successfully.
-->
<html>

<head>
<title>Email Verification</title>
</head>

<body>
<h1>{{appName}}</h1>
<h1>Email verified!</h1>
<p>Successfully verified your email for account: {{username}}.</p>
</body>

</html>
Loading

0 comments on commit 7f47b04

Please sign in to comment.