feat: Translated TOS/PP text!
* Pull translated TOS/PP text from repo using bower, convert to HTML using grunt. * Handle TOS/PP serving on the backend using new routes: `<locale>/legal/*` * If `locale` is not specified or cannot be found, use a fallback template. * Return 500 error with error message if a fallback template cannot be found. * Front end requests localized TOS/PP partials from the backend, on demand, and inserts them into the DOM. partial vs full html rendering is determined by `Accepts` header. Issue #634
This commit is contained in:
Родитель
0cb6e4a231
Коммит
26f680b3d1
|
@ -57,3 +57,7 @@ app/i18n
|
||||||
|
|
||||||
### Strings
|
### Strings
|
||||||
locale/*/*/*.po
|
locale/*/*/*.po
|
||||||
|
|
||||||
|
### Translated TOS/PP partial templates ###
|
||||||
|
server/templates/terms
|
||||||
|
server/templates/privacy
|
||||||
|
|
|
@ -3,100 +3,10 @@
|
||||||
<h1 id="fxa-pp-header">{{#t}}Privacy Notice{{/t}}</h1>
|
<h1 id="fxa-pp-header">{{#t}}Privacy Notice{{/t}}</h1>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section>
|
<section class="hidden">
|
||||||
|
<div class="error"></div>
|
||||||
|
|
||||||
<article id="legal-copy">
|
<article id="legal-copy">
|
||||||
<p>Last Updated January 31, 2014</p>
|
|
||||||
<p>We care about your privacy. When Firefox cloud services sends information to Mozilla (that's us), the Mozilla Privacy Policy below describes how we handle
|
|
||||||
that information.</p>
|
|
||||||
<p>Things you should know:</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>Firefox cloud services uses cookies and other web technologies to provide its functionality (such as remembering you between sessions) and to help us
|
|
||||||
understand how users use the service through aggregate analytics.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Firefox accounts sends Mozilla your email address and password. Firefox Sync sends Mozilla your tabs, awesome bar, passwords, bookmarks, and certain
|
|
||||||
browser preferences. We do not share this data with others and we use it solely to provide you with Firefox cloud services. If you request to have your
|
|
||||||
Firefox account deleted, we will no longer retain this information.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4>Mozilla Privacy Policy</h4>
|
|
||||||
<p>Your privacy is an important factor that Mozilla (that's us) considers in the development of each of our products and services. We are committed to being
|
|
||||||
transparent and open and want you to know how we receive information about you, and what we do with that information once we have it.</p>
|
|
||||||
|
|
||||||
<h4>What do we mean by "personal information?"</h4>
|
|
||||||
<p>For us, "personal information" means information which identifies you, like your name or email address.</p>
|
|
||||||
<p>Any information that falls outside of this is "non-personal information."</p>
|
|
||||||
<p>If we store your personal information with information that is non-personal, we will consider the combination as personal information. If we remove all
|
|
||||||
personal information from a set of data then the remaining is non-personal information.</p>
|
|
||||||
|
|
||||||
<h4>How do we learn information about you?</h4>
|
|
||||||
<p>We learn information about you when:</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>you give it to us directly (e.g., when you choose to send us crash reports from Firefox);</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>we collect it automatically through our products and services (e.g., when we check whether your version of Firefox is up to date);</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>someone else tells us information about you (e.g., Thunderbird works with your email providers to set up your account); or</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>when we try and understand more about you based on information you've given to us (e.g., when we use your IP address to customize language for some of our services).</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4>What do we do with your information once we have it?</h4>
|
|
||||||
<p>When you give us personal information, we will use it in the ways for which you've given us permission. Generally, we use your information to help us
|
|
||||||
provide and improve our products and services for you.</p>
|
|
||||||
|
|
||||||
<h4>When do we share your information with others?</h4>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>When we have gotten your permission to share it.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>For processing or providing products and services to you, but only if those entities receiving your information are contractually obligated to handle the
|
|
||||||
data in ways that are approved by Mozilla.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>When we are fulfilling our mission of <a href="http://www.mozilla.org/en-US/about/manifesto/" target="_blank">being open</a>. We sometimes release information to make our products better and foster an open web, but when we do so,
|
|
||||||
we will remove your personal information and try to disclose it in a way that minimizes the risk of you being re-identified.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>When the law requires it. We follow the law whenever we receive requests about you from a government or related to a lawsuit. We'll notify you when we're
|
|
||||||
asked to hand over your personal information in this way unless we're legally prohibited from doing so. When we receive requests like this, we'll only
|
|
||||||
release your personal information if we have a good faith belief that the law requires us to do so. Nothing in this policy is intended to limit any legal
|
|
||||||
defenses or objections that you may have to a third party's request to disclose your information.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>When we believe it is necessary to prevent harm to you or someone else. We will only share your information in this way if we have a good faith belief that
|
|
||||||
it is reasonably necessary to protect the rights, property or safety of you, our other users, Mozilla or the public.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>If our organizational structure or status changes (if we undergo a restructuring, are acquired, or go bankrupt) we may pass your information to a successor
|
|
||||||
or affiliate.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4>How do we store and protect your personal information?</h4>
|
|
||||||
<p>We are committed to protecting your personal information once we have it. We implement physical, business and technical security measures. Despite our
|
|
||||||
efforts, if we learn of a security breach, we'll notify you so that you can take appropriate protective steps.</p>
|
|
||||||
<p>We also don't want your personal information for any longer than we need it, so we only keep it long enough to do what we collected it for. Once we don't
|
|
||||||
need it, we take steps to destroy it unless we are required by law to keep it longer.</p>
|
|
||||||
|
|
||||||
<h4>What else do we want you know?</h4>
|
|
||||||
<p>We're a global organization and our computers are in several different places around the world. We also use service providers whose computers may also be
|
|
||||||
in various countries. This means that your information might end up on one of those computers in another country, and that country may have a different
|
|
||||||
level of data protection regulation than yours. By giving us information, you consent to this kind of transfer of your information. No matter what country
|
|
||||||
your information is in, we comply with applicable law and will also abide by the commitments we make in this privacy policy.</p>
|
|
||||||
<p>If you are under 13, we don't want your personal information, and you must not provide it to us. If you are a parent and believe that your child who is
|
|
||||||
under 13 has provided us with personal information, please <a href="https://www.mozilla.org/en-US/privacy/policies/firefox-os/" target="_blank">contact us</a> to have your child's information removed.</p>
|
|
||||||
|
|
||||||
<h4>What if we change this policy?</h4>
|
|
||||||
<p>We may need to change this policy and when we do, we'll notify you.</p>
|
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
{{#canGoBack}}
|
{{#canGoBack}}
|
||||||
|
|
|
@ -3,127 +3,10 @@
|
||||||
<h1 id="fxa-tos-header">{{#t}}Terms of Service{{/t}}</h1>
|
<h1 id="fxa-tos-header">{{#t}}Terms of Service{{/t}}</h1>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section>
|
<section class="hidden">
|
||||||
|
<div class="error"></div>
|
||||||
|
|
||||||
<article id="legal-copy">
|
<article id="legal-copy">
|
||||||
<p>Last Updated January 31, 2014</p>
|
|
||||||
<p>Thanks for choosing Firefox cloud services!</p>
|
|
||||||
|
|
||||||
<h4>Summary</h4>
|
|
||||||
<p>This top section summarizes the terms below. This summary is provided to help your understanding of the terms, but be sure to read the entire document, because when you agree to it, you are indicating you accept all of the terms, not just this summary.</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<p>
|
|
||||||
Firefox cloud services is a suite of services provided to you by Mozilla. You must be over the age of 13 to use Firefox cloud services or have your parent or guardian consent and supervise your use.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>
|
|
||||||
Firefox cloud services is designed to be a secure and easy way to connect with Mozilla and non-Mozilla services across devices so that you can access your profile whenever you need, from wherever you are.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>
|
|
||||||
Firefox cloud services are provided "as is" and there are no warranties of any kind. There are significant limits on Mozilla's liability for any damages arising from your use of Firefox cloud services.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4>Terms of Service</h4>
|
|
||||||
<ol>
|
|
||||||
<li>
|
|
||||||
<h4>Introduction</h4>
|
|
||||||
<p>
|
|
||||||
At Mozilla, we are committed to promoting choice and innovation on the web. That's why we created Firefox cloud services – a safe and easy way to connect your profile across devices whenever you need, from wherever you are. These Terms of Service ("<u>Terms</u>") govern your use of Firefox cloud services ("<u>Firefox Cloud Services</u>" or the "<u>Services</u>").
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Firefox Accounts</h4>
|
|
||||||
<p>
|
|
||||||
A Firefox account is needed to use the Services. You must be at least 13 years old to register for a Firefox account. During registration, you will be asked to set a password. You are responsible for keeping your password confidential and for the activity that happens through your Firefox account. Mozilla is not responsible for any losses arising out of unauthorized use of your Firefox account.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Firefox Sync </h4>
|
|
||||||
<p>
|
|
||||||
Firefox Sync allows you to access information stored in Firefox across devices, including your tabs, awesome bar, passwords, bookmarks, and certain browser preferences. You can enable and disable Firefox Sync through the Tools section of Firefox.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Your Data</h4>
|
|
||||||
<p>
|
|
||||||
You own any data that you submit to the Services. We encourage you to read our <a href="/legal/privacy">Privacy Notice</a> for details on our data practices. The Services connect to Mozilla and Non-Mozilla Services that may subject you to separate terms and privacy policies, and you are encouraged to read those documents.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Your Content in our Services</h4>
|
|
||||||
<p>
|
|
||||||
You are responsible for any intellectual property rights in content that you submit to our Services. By submitting content, you agree that you have the necessary rights to grant us and our applicable third party providers a license to use your content for the purpose of offering you the Services. This license includes the rights to reproduce, transmit, display, perform, modify, and store such content. You can terminate this license by removing your content from our Services.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>
|
|
||||||
<h4>Mozilla's Proprietary Rights </h4>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Mozilla does not grant you any intellectual property rights in the Services that are not specifically stated in these Terms. For example, these Terms do not provide the right to use any of Mozilla's copyrights, trade names, trademarks, service marks, logos, domain names, or other distinctive brand features. The Services are distributed under and subject to the current version of the <a href="http://www.mozilla.org/MPL/" target="_blank">Mozilla Public License</a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Term; Termination</h4>
|
|
||||||
<p>
|
|
||||||
These Terms will continue to apply until ended by either you or Mozilla. You can choose to end them at any time for any reason by deactivating your Firefox account and discontinuing your use of the Services.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
We may suspend or terminate your access to the Services at any time for any reason, including, but not limited to, if we reasonably believe: (i) you have violated these Terms, (ii) you create risk or possible legal exposure for us; or (iii) our provision of the Services to you is no longer commercially viable. We will make reasonable efforts to notify you by the email address associated with your Firefox account or the next time you attempt to access the Services.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
In all such cases, these Terms shall terminate, including, without limitation, your license to use the Services, except that the following sections shall continue to apply: Release and Indemnification, Disclaimer; Limitation of Liability, Miscellaneous.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Third Party Services</h4>
|
|
||||||
<p>
|
|
||||||
Third Party Services may have their own Privacy Policies and Terms of Use. You are encouraged to read these, because your use of Third Party Services may subject you to terms, policies, and practices that are separate from Mozilla's. Mozilla does not represent or imply that it endorses any Third Party Services nor that it believes the operation of any Third Party Services will be accurate, useful, or non-harmful. Third Party Services may have technical inaccuracies, may cause mistakes or errors, and may transmit, store, or otherwise manipulate data in a manner that you find objectionable. You are responsible for taking precautions to protect yourself and your computer systems in connection with the use of Third Party Services.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Release and Indemnification</h4>
|
|
||||||
<p>
|
|
||||||
You agree to defend, indemnify and hold harmless Mozilla, its contractors, contributors, licensors, and partners, and their respective directors, officers, employees and agents ("Indemnified Parties") from and against any and all third party claims and expenses, including attorneys' fees, arising out of your use of the Services.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Disclaimer; Limitation of Liability </h4>
|
|
||||||
<p class="allcaps">
|
|
||||||
The Services are provided "as is" with all faults. To the extent permitted by law, Mozilla AND THE INDEMNIFIED PARTIES hereby disclaim all warranties, whether express or implied, including without limitation warranties that the Services are free of defects, merchantable, fit for a particular purpose, and non-infringing. You bear the entire risk as to selecting the Services for your purposes and as to the quality and performance of the Services, including without limitation the risk that your Content is deleted or corrupted or that someone else uses your username and password to access your ACCOUNT. This limitation will apply notwithstanding the failure of essential purpose of any remedy. Some jurisdictions do not allow the exclusion or limitation of implied warranties, so this disclaimer may not apply to you.
|
|
||||||
</p>
|
|
||||||
<p class="allcaps">
|
|
||||||
Except as required by law, Mozilla AND THE INDEMNIFIED PARTIES will not be liable for any indirect, special, incidental, consequential, or exemplary damages arising out of or in any way relating to these Terms or the use of or inability to use the Services, including without limitation DIRECT AND INDIRECT damages for loss of goodwill, work stoppage, lost profits, loss of data, and computer failure or malfunction, even if advised of the possibility of such damages and regardless of the theory (contract, tort, or otherwise) upon which such claim is based. The collective liability of Mozilla AND THE INDEMNIFIED PARTIES under this Agreement will not exceed $500 (five hundred dollars). Some jurisdictions do not allow the exclusion or limitation of incidental, consequential, or special damages, so this exclusion and limitation may not apply to you.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Modifications to these Terms</h4>
|
|
||||||
<p>
|
|
||||||
Mozilla may update these Terms from time to time to address a new feature of the Services or to clarify a provision. The updated Terms will be posted online. If the changes are substantive, we will announce the update through Mozilla's usual channels for such announcements such as blog posts and forums. Your continued use of the Services after the effective date of such changes constitutes your acceptance of such changes. To make your review more convenient, we will post an effective date at the top of this page.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Miscellaneous</h4>
|
|
||||||
<p>
|
|
||||||
These Terms constitute the entire agreement between you and Mozilla concerning the Services and are governed by the laws of the state of California, U.S.A., excluding its conflict of law provisions. If any portion of these Terms is held to be invalid or unenforceable, the remaining portions will remain in full force and effect. In the event of a conflict between a translated version of these terms and the English language version, the English language version shall control.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h4>Contact Us</h4>
|
|
||||||
<p>Contact Mozilla at</p>
|
|
||||||
<address>
|
|
||||||
Mozilla Corporation<br>
|
|
||||||
Attn: Mozilla – Legal Notices<br>
|
|
||||||
2 Harrison St,<br>
|
|
||||||
San Francisco, CA 94105<br>
|
|
||||||
</address>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
{{#canGoBack}}
|
{{#canGoBack}}
|
||||||
|
|
|
@ -5,11 +5,15 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
define([
|
define([
|
||||||
|
'jquery',
|
||||||
'views/base',
|
'views/base',
|
||||||
'stache!templates/pp',
|
'stache!templates/pp',
|
||||||
'lib/session'
|
'lib/session',
|
||||||
|
'lib/strings'
|
||||||
],
|
],
|
||||||
function (BaseView, Template, Session) {
|
function ($, BaseView, Template, Session, Strings) {
|
||||||
|
var t = BaseView.t;
|
||||||
|
|
||||||
var View = BaseView.extend({
|
var View = BaseView.extend({
|
||||||
template: Template,
|
template: Template,
|
||||||
className: 'pp',
|
className: 'pp',
|
||||||
|
@ -20,6 +24,28 @@ function (BaseView, Template, Session) {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
afterRender: function () {
|
||||||
|
var self = this;
|
||||||
|
$.ajax({
|
||||||
|
url: Strings.interpolate('/%s/legal/privacy', [Session.language]),
|
||||||
|
accepts: {
|
||||||
|
text: 'text/partial'
|
||||||
|
},
|
||||||
|
dataType: 'text'
|
||||||
|
})
|
||||||
|
.done(function(template) {
|
||||||
|
self.$('#legal-copy').html(template);
|
||||||
|
self.$('.hidden').removeClass('hidden');
|
||||||
|
})
|
||||||
|
.fail(function() {
|
||||||
|
self.displayError(t('Could not get Privacy Notice'));
|
||||||
|
self.$('.hidden').removeClass('hidden');
|
||||||
|
})
|
||||||
|
.always(function() {
|
||||||
|
self.trigger('ready');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click #fxa-pp-back': 'back',
|
'click #fxa-pp-back': 'back',
|
||||||
'keyup #fxa-pp-back': 'backOnEnter'
|
'keyup #fxa-pp-back': 'backOnEnter'
|
||||||
|
|
|
@ -5,11 +5,15 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
define([
|
define([
|
||||||
|
'jquery',
|
||||||
'views/base',
|
'views/base',
|
||||||
'stache!templates/tos',
|
'stache!templates/tos',
|
||||||
'lib/session'
|
'lib/session',
|
||||||
|
'lib/strings'
|
||||||
],
|
],
|
||||||
function (BaseView, Template, Session) {
|
function ($, BaseView, Template, Session, Strings) {
|
||||||
|
var t = BaseView.t;
|
||||||
|
|
||||||
var View = BaseView.extend({
|
var View = BaseView.extend({
|
||||||
template: Template,
|
template: Template,
|
||||||
className: 'tos',
|
className: 'tos',
|
||||||
|
@ -20,6 +24,28 @@ function (BaseView, Template, Session) {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
afterRender: function () {
|
||||||
|
var self = this;
|
||||||
|
$.ajax({
|
||||||
|
url: Strings.interpolate('/%s/legal/terms', [Session.language]),
|
||||||
|
accepts: {
|
||||||
|
text: 'text/partial'
|
||||||
|
},
|
||||||
|
dataType: 'text'
|
||||||
|
})
|
||||||
|
.done(function(template) {
|
||||||
|
self.$('#legal-copy').html(template);
|
||||||
|
self.$('.hidden').removeClass('hidden');
|
||||||
|
})
|
||||||
|
.fail(function() {
|
||||||
|
self.displayError(t('Could not get Terms of Service'));
|
||||||
|
self.$('.hidden').removeClass('hidden');
|
||||||
|
})
|
||||||
|
.always(function() {
|
||||||
|
self.trigger('ready');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click #fxa-tos-back': 'back',
|
'click #fxa-tos-back': 'back',
|
||||||
'keyup #fxa-tos-back': 'backOnEnter'
|
'keyup #fxa-tos-back': 'backOnEnter'
|
||||||
|
|
|
@ -655,8 +655,6 @@ input[type="text"] ~ .show-password-label:hover {
|
||||||
width: 36px;
|
width: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: (Issue #558) These need further consideration */
|
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,19 @@ function (chai, View, Session) {
|
||||||
|
|
||||||
assert.equal($('#fxa-pp-back').length, 0);
|
assert.equal($('#fxa-pp-back').length, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('fetches translated text from the backend', function (done) {
|
||||||
|
Session.set('language', 'en-US');
|
||||||
|
view.on('ready', function() {
|
||||||
|
// there is currently an error in the tos/pp repo where the tos
|
||||||
|
// is under the pp dir, and the pp us under the tos dir.
|
||||||
|
/*assert.ok(view.$('#mozilla-privacy-policy').length);*/
|
||||||
|
assert.ok(view.$('#terms-of-service').length);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
view.render();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,19 @@ function (chai, View, Session) {
|
||||||
|
|
||||||
assert.equal($('#fxa-tos-back').length, 0);
|
assert.equal($('#fxa-tos-back').length, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('fetches translated text from the backend', function (done) {
|
||||||
|
Session.set('language', 'en-US');
|
||||||
|
view.on('ready', function() {
|
||||||
|
// there is currently an error in the tos/pp repo where the tos
|
||||||
|
// is under the pp dir, and the pp us under the tos dir.
|
||||||
|
assert.ok(view.$('#mozilla-privacy-policy').length);
|
||||||
|
/*assert.ok(view.$('#terms-of-service').length);*/
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
view.render();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
"p": "https://github.com/rkatic/p.git#c6a451ef6080f10f9c31489c127ca3b291d0bc5a",
|
"p": "https://github.com/rkatic/p.git#c6a451ef6080f10f9c31489c127ca3b291d0bc5a",
|
||||||
"sinon": "http://sinonjs.org/releases/sinon-1.7.1.js",
|
"sinon": "http://sinonjs.org/releases/sinon-1.7.1.js",
|
||||||
"fxa-content-server-l10n": "https://github.com/mozilla/fxa-content-server-l10n.git",
|
"fxa-content-server-l10n": "https://github.com/mozilla/fxa-content-server-l10n.git",
|
||||||
"blanket": "1.1.5"
|
"blanket": "1.1.5",
|
||||||
|
"tos-pp": "https://github.com/mozilla/legal-docs.git"
|
||||||
},
|
},
|
||||||
"devDependencies": {}
|
"devDependencies": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ module.exports = function (grunt) {
|
||||||
'useminPrepare',
|
'useminPrepare',
|
||||||
'selectconfig:dist',
|
'selectconfig:dist',
|
||||||
'l10n-create-json',
|
'l10n-create-json',
|
||||||
|
'l10n-generate-tos-pp:dist',
|
||||||
// server templates are needed for requirejs to replace the require script
|
// server templates are needed for requirejs to replace the require script
|
||||||
'copy:server_templates',
|
'copy:server_templates',
|
||||||
'requirejs',
|
'requirejs',
|
||||||
|
|
|
@ -6,6 +6,15 @@ module.exports = function (grunt) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
grunt.config('clean', {
|
grunt.config('clean', {
|
||||||
|
tos_pp: {
|
||||||
|
files: [{
|
||||||
|
dot: true,
|
||||||
|
src: [
|
||||||
|
'<%= yeoman.pp_html_dest %>',
|
||||||
|
'<%= yeoman.tos_html_dest %>'
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
dist: {
|
dist: {
|
||||||
files: [{
|
files: [{
|
||||||
dot: true,
|
dot: true,
|
||||||
|
@ -17,6 +26,13 @@ module.exports = function (grunt) {
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
server: '.tmp'
|
app: {
|
||||||
|
files: [{
|
||||||
|
dot: true,
|
||||||
|
src: [
|
||||||
|
'<%= yeoman.tmp %>/*'
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
// grunt task to extract strings.
|
||||||
|
module.exports = function (grunt) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
grunt.registerTask('l10n-generate-tos-pp',
|
||||||
|
'Generate translated TOS/PP agreement partial templates',
|
||||||
|
function () {
|
||||||
|
|
||||||
|
grunt.task.run([
|
||||||
|
'clean:tos_pp',
|
||||||
|
'marked:tos_pp'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
module.exports = function (grunt) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// convert localized TOS/PP agreements from markdown to html partials.
|
||||||
|
|
||||||
|
grunt.config('marked', {
|
||||||
|
options: {
|
||||||
|
sanitize: false,
|
||||||
|
gfm: true
|
||||||
|
},
|
||||||
|
tos_pp: {
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
expand: true,
|
||||||
|
cwd: '<%= yeoman.pp_md_src %>',
|
||||||
|
src: ['**/*.md'],
|
||||||
|
dest: '<%= yeoman.pp_html_dest %>',
|
||||||
|
ext: '.html'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expand: true,
|
||||||
|
cwd: '<%= yeoman.tos_md_src %>',
|
||||||
|
src: ['**/*.md'],
|
||||||
|
dest: '<%= yeoman.tos_html_dest %>',
|
||||||
|
ext: '.html'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
|
@ -11,8 +11,9 @@ module.exports = function (grunt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
grunt.task.run([
|
grunt.task.run([
|
||||||
'clean:server',
|
'clean:app',
|
||||||
'selectconfig:app',
|
'selectconfig:app',
|
||||||
|
'l10n-generate-tos-pp:app',
|
||||||
'css',
|
'css',
|
||||||
'concurrent:server',
|
'concurrent:server',
|
||||||
'serverproc:app'
|
'serverproc:app'
|
||||||
|
|
|
@ -6,7 +6,7 @@ module.exports = function (grunt) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
grunt.registerTask('test', [
|
grunt.registerTask('test', [
|
||||||
'clean:server',
|
'clean:app',
|
||||||
'css',
|
'css',
|
||||||
'concurrent:test',
|
'concurrent:test',
|
||||||
'serverproc:test'
|
'serverproc:test'
|
||||||
|
|
|
@ -5,15 +5,25 @@
|
||||||
module.exports = function (grunt) {
|
module.exports = function (grunt) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var TEMP_DIR = '.tmp';
|
||||||
|
var TEMPLATE_ROOT = 'server/templates';
|
||||||
|
var TOS_PP_REPO_ROOT = 'app/bower_components/tos-pp';
|
||||||
|
|
||||||
grunt.config('yeoman', {
|
grunt.config('yeoman', {
|
||||||
app: 'app',
|
app: 'app',
|
||||||
dist: 'dist',
|
dist: 'dist',
|
||||||
server: 'fxa-auth-server',
|
server: 'fxa-auth-server',
|
||||||
page_template_src: 'server/templates/pages/src',
|
page_template_src: TEMPLATE_ROOT + '/pages/src',
|
||||||
page_template_dist: 'server/templates/pages/dist',
|
page_template_dist: TEMPLATE_ROOT + '/pages/dist',
|
||||||
strings_src: 'app/bower_components/fxa-content-server-l10n/locale',
|
strings_src: 'app/bower_components/fxa-content-server-l10n/locale',
|
||||||
strings_dist: 'locale',
|
strings_dist: 'locale',
|
||||||
tests: 'tests',
|
tests: 'tests',
|
||||||
tmp: '.tmp'
|
tmp: TEMP_DIR,
|
||||||
|
// Translated TOS/PP agreements.
|
||||||
|
tos_pp_repo_dest: TOS_PP_REPO_ROOT,
|
||||||
|
tos_md_src: TOS_PP_REPO_ROOT + '/firefox_online_services_ToS/',
|
||||||
|
tos_html_dest: TEMPLATE_ROOT + '/terms',
|
||||||
|
pp_md_src: TOS_PP_REPO_ROOT + '/firefox_online_services_PrivacyNotice/',
|
||||||
|
pp_html_dest: TEMPLATE_ROOT + '/privacy'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -4064,6 +4064,24 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"grunt-marked": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"from": "grunt-marked@",
|
||||||
|
"dependencies": {
|
||||||
|
"marked": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"from": "marked@~0.3.1"
|
||||||
|
},
|
||||||
|
"async": {
|
||||||
|
"version": "0.2.10",
|
||||||
|
"from": "async@~0.2.10"
|
||||||
|
},
|
||||||
|
"highlight.js": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"from": "highlight.js@~8.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"grunt-mocha": {
|
"grunt-mocha": {
|
||||||
"version": "0.4.10",
|
"version": "0.4.10",
|
||||||
"from": "https://registry.npmjs.org/grunt-mocha/-/grunt-mocha-0.4.10.tgz",
|
"from": "https://registry.npmjs.org/grunt-mocha/-/grunt-mocha-0.4.10.tgz",
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
"grunt-copyright": "0.1.0",
|
"grunt-copyright": "0.1.0",
|
||||||
"grunt-jscs-checker": "0.4.0",
|
"grunt-jscs-checker": "0.4.0",
|
||||||
"grunt-jsonlint": "1.0.4",
|
"grunt-jsonlint": "1.0.4",
|
||||||
|
"grunt-marked": "0.1.0",
|
||||||
"grunt-mocha": "0.4.10",
|
"grunt-mocha": "0.4.10",
|
||||||
"grunt-modernizr": "0.5.1",
|
"grunt-modernizr": "0.5.1",
|
||||||
"grunt-nsp-shrinkwrap": "0.0.3",
|
"grunt-nsp-shrinkwrap": "0.0.3",
|
||||||
|
|
|
@ -95,8 +95,6 @@ module.exports = function (config, templates) {
|
||||||
'/settings',
|
'/settings',
|
||||||
'/change_password',
|
'/change_password',
|
||||||
'/legal',
|
'/legal',
|
||||||
'/legal/terms',
|
|
||||||
'/legal/privacy',
|
|
||||||
'/cannot_create_account',
|
'/cannot_create_account',
|
||||||
'/verify_email',
|
'/verify_email',
|
||||||
'/reset_password',
|
'/reset_password',
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <locale>/legal/terms and <locale>/legal/privacy
|
||||||
|
* Translation done by fetching appropriate template for language.
|
||||||
|
* If language is not found, fall back to en-US.
|
||||||
|
*
|
||||||
|
* Either full HTML or a partial can be requested. Partials are
|
||||||
|
* requested by the front end to request translated documents and
|
||||||
|
* insert them into the DOM. Full HTML is used whenever a user
|
||||||
|
* browses to one of the pages directly.
|
||||||
|
*
|
||||||
|
* Partials are requested by setting the `Accepts` header to `text/partial`
|
||||||
|
* HTML is returned if `Accepts` is `text/html`
|
||||||
|
*/
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var logger = require('intel').getLogger('route.get-terms-privacy');
|
||||||
|
var Promise = require('bluebird');
|
||||||
|
|
||||||
|
var TOS_ROOT_PATH = path.join(__dirname, '..', '..', 'templates', 'terms');
|
||||||
|
var PP_ROOT_PATH = path.join(__dirname, '..', '..', 'templates', 'privacy');
|
||||||
|
|
||||||
|
var DEFAULT_LANG = 'en-US';
|
||||||
|
|
||||||
|
exports.method = 'get';
|
||||||
|
|
||||||
|
// Match (allow for optional trailing slash):
|
||||||
|
// * /legal/terms
|
||||||
|
// * /<locale>/legal/terms
|
||||||
|
// * /legal/privacy
|
||||||
|
// * /<locale>/legal/privacy
|
||||||
|
exports.path = /^\/(?:([a-zA-Z-\_]*)\/)?legal\/(terms|privacy)(?:\/)?$/;
|
||||||
|
|
||||||
|
function getRoot(type) {
|
||||||
|
return type === 'terms' ? TOS_ROOT_PATH : PP_ROOT_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLanguage(lang) {
|
||||||
|
// filenames have a '-' in them, browsers report with a '_'.
|
||||||
|
return lang.replace(/_/g, '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
var resolverCache = {};
|
||||||
|
function getTemplate(type, lang, done) {
|
||||||
|
lang = normalizeLanguage(lang);
|
||||||
|
var templatePath = path.join(getRoot(type), lang + '.html');
|
||||||
|
|
||||||
|
// cache the promises to avoid multiple concurrent checks for
|
||||||
|
// the same template due to async calls to the file system.
|
||||||
|
if (resolverCache[templatePath]) {
|
||||||
|
return resolverCache[templatePath].promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resolver = Promise.defer();
|
||||||
|
resolverCache[templatePath] = resolver;
|
||||||
|
|
||||||
|
fs.exists(templatePath, function (exists) {
|
||||||
|
if (! exists) {
|
||||||
|
if (lang === DEFAULT_LANG) {
|
||||||
|
var err = new Error(type + ' missing `' + DEFAULT_LANG + '` template');
|
||||||
|
return resolver.reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolver.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.readFile(templatePath, 'utf8', function(err, data) {
|
||||||
|
if (err) {
|
||||||
|
return resolver.reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolver.resolve(data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return resolver.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.process = function (req, res) {
|
||||||
|
var lang = req.params[0];
|
||||||
|
var page = req.params[1];
|
||||||
|
|
||||||
|
if (! lang) {
|
||||||
|
// abide should put a lang on the request, if not, use the default.
|
||||||
|
return res.redirect(getRedirectURL(req.lang || DEFAULT_LANG, page));
|
||||||
|
}
|
||||||
|
|
||||||
|
getTemplate(page, lang)
|
||||||
|
.then(function (template) {
|
||||||
|
if ( ! template) {
|
||||||
|
logger.warn('%s->`%s` does not exist, redirecting to `%s`',
|
||||||
|
page, lang, DEFAULT_LANG);
|
||||||
|
return res.redirect(getRedirectURL(DEFAULT_LANG, page));
|
||||||
|
}
|
||||||
|
|
||||||
|
res.format({
|
||||||
|
'text/partial': function () {
|
||||||
|
res.send(template);
|
||||||
|
},
|
||||||
|
'text/html': function () {
|
||||||
|
res.render(page, { body: template });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, function(err) {
|
||||||
|
logger.error(err);
|
||||||
|
return res.send(500, 'uh oh: ' + String(err));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function getRedirectURL(lang, page) {
|
||||||
|
return lang + '/legal/' + page;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
<!doctype html>
|
||||||
|
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||||
|
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||||
|
<!--[if IE 8]> <html class="lt-ie9"> <![endif]-->
|
||||||
|
<!--[if gt IE 8]><!--> <html> <!--<![endif]-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<title>{{#t}}Firefox Accounts{{/t}}: {{#t}}Privacy Notice{{/t}}</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
|
||||||
|
<link rel="stylesheet" href="/latin/firasans-regular,firasans-light,clearsans-regular/fonts.css">
|
||||||
|
<!-- build:css(.tmp) /styles/main.css -->
|
||||||
|
<link rel="stylesheet" href="/bower_components/normalize-css/normalize.css">
|
||||||
|
<link rel="stylesheet" href="/styles/main.css">
|
||||||
|
<!-- endbuild -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="stage">
|
||||||
|
<header id="legal-header">
|
||||||
|
<h1 class="fox-logo"><span>{{#t}}Firefox Accounts{{/t}}</span></h1>
|
||||||
|
<h3>{{#t}}Firefox cloud services{{/t}}</h3>
|
||||||
|
<h2 id="fxa-pp-header">{{#t}}Privacy Notice{{/t}}</h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<article id="legal-copy">
|
||||||
|
{{{ body }}}
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<!doctype html>
|
||||||
|
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||||
|
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||||
|
<!--[if IE 8]> <html class="lt-ie9"> <![endif]-->
|
||||||
|
<!--[if gt IE 8]><!--> <html> <!--<![endif]-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<title>{{#t}}Firefox Accounts{{/t}}: {{#t}}Terms of Service{{/t}}</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
|
||||||
|
<link rel="stylesheet" href="/latin/firasans-regular,firasans-light,clearsans-regular/fonts.css">
|
||||||
|
<!-- build:css(.tmp) /styles/main.css -->
|
||||||
|
<link rel="stylesheet" href="/bower_components/normalize-css/normalize.css">
|
||||||
|
<link rel="stylesheet" href="/styles/main.css">
|
||||||
|
<!-- endbuild -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="stage">
|
||||||
|
<header id="legal-header">
|
||||||
|
<h1 class="fox-logo"><span>{{#t}}Firefox Accounts{{/t}}</span></h1>
|
||||||
|
<h3>{{#t}}Firefox cloud services{{/t}}</h3>
|
||||||
|
<h2 id="fxa-tos-header">{{#t}}Terms of Service{{/t}}</h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<article id="legal-copy">
|
||||||
|
{{{ body }}}
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -25,8 +25,17 @@ define([
|
||||||
'settings',
|
'settings',
|
||||||
'change_password',
|
'change_password',
|
||||||
'legal',
|
'legal',
|
||||||
|
// legal are all redirected to the language detected
|
||||||
|
// by sniffing headers, barring that, using en-US as
|
||||||
|
// the fallback.
|
||||||
'legal/terms',
|
'legal/terms',
|
||||||
'legal/privacy',
|
'legal/privacy',
|
||||||
|
// invalid-locale should be redirected to en-US
|
||||||
|
'invalid-locale/legal/terms',
|
||||||
|
'invalid-locale/legal/privacy',
|
||||||
|
// yay!
|
||||||
|
'en-US/legal/terms',
|
||||||
|
'en-US/legal/privacy',
|
||||||
'reset_password',
|
'reset_password',
|
||||||
'confirm_reset_password',
|
'confirm_reset_password',
|
||||||
'complete_reset_password',
|
'complete_reset_password',
|
||||||
|
|
|
@ -39,7 +39,9 @@ define([
|
||||||
'/tests/index.html': 200,
|
'/tests/index.html': 200,
|
||||||
'/tests/index.html?coverage': 200,
|
'/tests/index.html?coverage': 200,
|
||||||
'/ver.json': 200,
|
'/ver.json': 200,
|
||||||
'/non_existent': 404
|
'/non_existent': 404,
|
||||||
|
'/legal/non_existent': 404,
|
||||||
|
'/en-US/legal/non_existent': 404
|
||||||
};
|
};
|
||||||
|
|
||||||
function routeTest(route, expectedStatusCode) {
|
function routeTest(route, expectedStatusCode) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче