Improve flows for social auth users (#13862)

* Multiple fixes for social authentication flows

* frontend changes

* add missing computed property

* Improvements to social flows

* fix existing email error

* minor fixes

* fix space

* fix test

* fix lint

Co-authored-by: SabreCat <sabe@habitica.com>
This commit is contained in:
Phillip Thelen
2022-03-31 23:43:16 +02:00
committed by GitHub
parent 9ff0766910
commit 55cf2f9795
19 changed files with 213 additions and 88 deletions

View File

@@ -84,8 +84,8 @@
</li> </li>
<li v-if="user"> <li v-if="user">
<a <a
@click.prevent="openBugReportModal()"
target="_blank" target="_blank"
@click.prevent="openBugReportModal()"
> >
{{ $t('reportBug') }} {{ $t('reportBug') }}
</a> </a>

View File

@@ -20,8 +20,8 @@
</div> </div>
</div> </div>
<div <div
class="form-group row text-center"
v-if="!registering" v-if="!registering"
class="form-group row text-center"
> >
<div class="col-12 col-md-12"> <div class="col-12 col-md-12">
<div <div
@@ -269,13 +269,13 @@
<label <label
v-once v-once
for="usernameInput" for="usernameInput"
>{{ $t('email') }}</label> >{{ $t('emailOrUsername') }}</label>
<input <input
id="usernameInput" id="usernameInput"
v-model="username" v-model="username"
class="form-control" class="form-control"
type="text" type="text"
:placeholder="$t('emailPlaceholder')" :placeholder="$t('emailUsernamePlaceholder')"
> >
</div> </div>
<div class="text-center"> <div class="text-center">

View File

@@ -12,12 +12,18 @@
{{ $t('reportBug') }} {{ $t('reportBug') }}
</h2> </h2>
<div v-once class="report-bug-header-describe"> <div
v-once
class="report-bug-header-describe"
>
{{ $t('reportBugHeaderDescribe') }} {{ $t('reportBugHeaderDescribe') }}
</div> </div>
<div class="dialog-close"> <div class="dialog-close">
<close-icon @click="close()" :purple="true"/> <close-icon
:purple="true"
@click="close()"
/>
</div> </div>
</div> </div>
<div> <div>
@@ -34,7 +40,10 @@
> >
{{ $t('email') }} {{ $t('email') }}
</label> </label>
<div class="mb-2 description-label" v-once> <div
v-once
class="mb-2 description-label"
>
{{ $t('reportEmailText') }} {{ $t('reportEmailText') }}
</div> </div>
<input <input
@@ -47,7 +56,10 @@
:class="{'input-invalid': emailInvalid, 'input-valid': emailValid}" :class="{'input-invalid': emailInvalid, 'input-valid': emailValid}"
> >
<div class="error-label mt-2" v-if="emailInvalid"> <div
v-if="emailInvalid"
class="error-label mt-2"
>
{{ $t('reportEmailError') }} {{ $t('reportEmailError') }}
</div> </div>
</div> </div>
@@ -55,7 +67,10 @@
<label v-once> <label v-once>
{{ $t('reportDescription') }} {{ $t('reportDescription') }}
</label> </label>
<div class="mb-2 description-label" v-once> <div
v-once
class="mb-2 description-label"
>
{{ $t('reportDescriptionText') }} {{ $t('reportDescriptionText') }}
</div> </div>
<textarea <textarea

View File

@@ -17,15 +17,22 @@
</div> </div>
</div> </div>
<div> <div>
<span class="svg-icon check-icon" <span
v-html="icons.checkCircleIcon" class="svg-icon check-icon"
v-html="icons.checkCircleIcon"
></span> ></span>
<div class="title" v-once> <div
v-once
class="title"
>
{{ $t('reportSent') }} {{ $t('reportSent') }}
</div> </div>
<div class="text mt-3 mb-4" v-once> <div
v-once
class="text mt-3 mb-4"
>
{{ $t('reportSentDescription') }} {{ $t('reportSentDescription') }}
</div> </div>
</div> </div>
@@ -143,12 +150,12 @@ export default {
modalId: MODALS.BUG_REPORT_SUCCESS, modalId: MODALS.BUG_REPORT_SUCCESS,
}; };
}, },
computed: {},
mounted () {},
methods: { methods: {
close () { close () {
this.$root.$emit('bv::hide::modal', MODALS.BUG_REPORT_SUCCESS); this.$root.$emit('bv::hide::modal', MODALS.BUG_REPORT_SUCCESS);
}, },
}, },
computed: {},
mounted () {},
}; };
</script> </script>

View File

@@ -361,8 +361,8 @@
</li> </li>
<li> <li>
<a <a
@click.prevent="openBugReportModal()"
target="_blank" target="_blank"
@click.prevent="openBugReportModal()"
> >
{{ $t('reportBug') }} {{ $t('reportBug') }}
</a> </a>

View File

@@ -311,8 +311,8 @@
</router-link> </router-link>
<a <a
class="topbar-dropdown-item dropdown-item" class="topbar-dropdown-item dropdown-item"
@click.prevent="openBugReportModal()"
target="_blank" target="_blank"
@click.prevent="openBugReportModal()"
> >
{{ $t('reportBug') }} {{ $t('reportBug') }}
</a> </a>

View File

@@ -7,9 +7,9 @@
> >
<div class="modal-body"> <div class="modal-body">
<br> <br>
<strong v-if="user.auth.local.email">{{ $t('deleteLocalAccountText') }}</strong> <strong v-if="user.auth.local.has_password">{{ $t('deleteLocalAccountText') }}</strong>
<strong <strong
v-if="!user.auth.local.email" v-if="!user.auth.local.has_password"
>{{ $t('deleteSocialAccountText', {magicWord: 'DELETE'}) }}</strong> >{{ $t('deleteSocialAccountText', {magicWord: 'DELETE'}) }}</strong>
<div class="row mt-3"> <div class="row mt-3">
<div class="col-6"> <div class="col-6">

View File

@@ -291,14 +291,22 @@
</li> </li>
</ul> </ul>
<hr> <hr>
<div v-if="!user.auth.local.email"> <div v-if="!user.auth.local.has_password">
<p>{{ $t('addLocalAuth') }}</p> <h5 v-if="!user.auth.local.email">
{{ $t('addLocalAuth') }}
</h5>
<h5 v-if="user.auth.local.email">
{{ $t('addPasswordAuth') }}
</h5>
<div <div
class="form" class="form"
name="localAuth" name="localAuth"
novalidate="novalidate" novalidate="novalidate"
> >
<div class="form-group"> <div
v-if="!user.auth.local.email"
class="form-group"
>
<input <input
v-model="localAuth.email" v-model="localAuth.email"
class="form-control" class="form-control"
@@ -421,7 +429,7 @@
{{ $t('saveAndConfirm') }} {{ $t('saveAndConfirm') }}
</button> </button>
</div> </div>
<h5 v-if="user.auth.local.email"> <h5>
{{ $t('changeEmail') }} {{ $t('changeEmail') }}
</h5> </h5>
<div <div
@@ -439,7 +447,10 @@
:placeholder="$t('newEmail')" :placeholder="$t('newEmail')"
> >
</div> </div>
<div class="form-group"> <div
v-if="user.auth.local.has_password"
class="form-group"
>
<input <input
v-model="emailUpdates.password" v-model="emailUpdates.password"
class="form-control" class="form-control"
@@ -455,11 +466,11 @@
{{ $t('submit') }} {{ $t('submit') }}
</button> </button>
</div> </div>
<h5 v-if="user.auth.local.email"> <h5 v-if="user.auth.local.has_password">
{{ $t('changePass') }} {{ $t('changePass') }}
</h5> </h5>
<div <div
v-if="user.auth.local.email" v-if="user.auth.local.has_password"
class="form" class="form"
name="changePassword" name="changePassword"
novalidate="novalidate" novalidate="novalidate"
@@ -846,7 +857,7 @@ export default {
if (network === 'apple') { if (network === 'apple') {
window.location.href = buildAppleAuthUrl(); window.location.href = buildAppleAuthUrl();
} else { } else {
const auth = await hello(network).login({ scope: 'email' }); const auth = await hello(network).login({ scope: 'email', options: { force: true } });
await this.$store.dispatch('auth:socialAuth', { await this.$store.dispatch('auth:socialAuth', {
auth, auth,
@@ -865,8 +876,12 @@ export default {
} }
}, },
async addLocalAuth () { async addLocalAuth () {
if (this.localAuth.email === '') {
this.localAuth.email = this.user.auth.local.email;
}
await axios.post('/api/v4/user/auth/local/register', this.localAuth); await axios.post('/api/v4/user/auth/local/register', this.localAuth);
window.alert(this.$t('addedLocalAuth')); // eslint-disable-line no-alert window.alert(this.$t('addedLocalAuth')); // eslint-disable-line no-alert
window.location.href = '/';
}, },
restoreEmptyUsername () { restoreEmptyUsername () {
if (this.usernameUpdates.username.length < 1) { if (this.usernameUpdates.username.length < 1) {

View File

@@ -1,12 +1,12 @@
<template> <template>
<button <button
title="close dialog" title="close dialog"
@click="$emit('click', $event)"
:style="{ :style="{
'--icon-color': iconColor, '--icon-color': iconColor,
'--icon-color-hover': iconColorHover, '--icon-color-hover': iconColorHover,
}" }"
:class="{'purple': purple}" :class="{'purple': purple}"
@click="$emit('click', $event)"
> >
<div <div
v-once v-once

View File

@@ -10,8 +10,8 @@
<span v-if="user"> <span v-if="user">
<br> <br>
<a <a
@click.prevent="openBugReportModal()"
target="_blank" target="_blank"
@click.prevent="openBugReportModal()"
> >
{{ $t('reportBug') }} {{ $t('reportBug') }}
</a> </a>

View File

@@ -8,7 +8,7 @@
<p> <p>
HabitRPG, Inc. (HabitRPG, we, us, or our) welcomes you. This privacy notice (the Privacy HabitRPG, Inc. (HabitRPG, we, us, or our) welcomes you. This privacy notice (the Privacy
Notice) describes how we process the information we collect about or from you through our Website Notice) describes how we process the information we collect about or from you through our Website
located at <a href='https://habitica.com/static/home'>https://habitica.com/static/home</a> and/or our Apps located at <a href="https://habitica.com/static/home">https://habitica.com/static/home</a> and/or our Apps
(our Digital Platforms), from our users, subscribers, visitors and other users of our technology and (our Digital Platforms), from our users, subscribers, visitors and other users of our technology and
platforms (together with our Digital Platforms, the Habitica Service or the Service), and when you platforms (together with our Digital Platforms, the Habitica Service or the Service), and when you
otherwise interact with us. This Privacy Notice may be updated by us from time to time without notice to otherwise interact with us. This Privacy Notice may be updated by us from time to time without notice to
@@ -65,11 +65,36 @@
policies linked to below: policies linked to below:
</p> </p>
<ul> <ul>
<li>For Stripe, visit: <a href='https://stripe.com/privacy' target='_blank'>https://stripe.com/privacy</a></li> <li>
<li>For Amazon Pay, visit: <a href='https://pay.amazon.com/help/201751600' target='_blank'>https://pay.amazon.com/help/201751600</a></li> For Stripe, visit: <a
<li>For PayPal, visit: <a href='https://www.paypal.com/us/webapps/mpp/ua/privacy-full' target='_blank'>https://www.paypal.com/us/webapps/mpp/ua/privacy-full</a></li> href="https://stripe.com/privacy"
<li>For Apple Pay, visit: <a href='https://www.apple.com/legal/privacy/data/en/apple-pay/' target='_blank'>https://www.apple.com/legal/privacy/data/en/apple-pay/</a></li> target="_blank"
<li>For Google Pay, visit: <a href='https://support.google.com/googlepay/answer/10223752?hl=en&co=GENIE.Platform%3DAndroid' target='_blank'>https://support.google.com/googlepay/answer/10223752?hl=en&co=GENIE.Platform%3DAndroid</a></li> >https://stripe.com/privacy</a>
</li>
<li>
For Amazon Pay, visit: <a
href="https://pay.amazon.com/help/201751600"
target="_blank"
>https://pay.amazon.com/help/201751600</a>
</li>
<li>
For PayPal, visit: <a
href="https://www.paypal.com/us/webapps/mpp/ua/privacy-full"
target="_blank"
>https://www.paypal.com/us/webapps/mpp/ua/privacy-full</a>
</li>
<li>
For Apple Pay, visit: <a
href="https://www.apple.com/legal/privacy/data/en/apple-pay/"
target="_blank"
>https://www.apple.com/legal/privacy/data/en/apple-pay/</a>
</li>
<li>
For Google Pay, visit: <a
href="https://support.google.com/googlepay/answer/10223752?hl=en&co=GENIE.Platform%3DAndroid"
target="_blank"
>https://support.google.com/googlepay/answer/10223752?hl=en&co=GENIE.Platform%3DAndroid</a>
</li>
</ul> </ul>
<p> <p>
We reserve the right to change our payment vendors at any time, or to use additional payment vendors, at We reserve the right to change our payment vendors at any time, or to use additional payment vendors, at
@@ -95,22 +120,32 @@
see the information regarding analytics providers discussed further below. see the information regarding analytics providers discussed further below.
</p> </p>
<ul> <ul>
<li><strong>Session Cookies</strong>: We use session cookies to make it easier for you to navigate our Service. A <li>
session ID cookie expires when you close the Service.</li> <strong>Session Cookies</strong>: We use session cookies to make it easier for you to navigate our Service. A
<li><strong>Persistent Cookies</strong>: A persistent cookie remains on your device for an extended period of time or session ID cookie expires when you close the Service.
</li>
<li>
<strong>Persistent Cookies</strong>: A persistent cookie remains on your device for an extended period of time or
until you delete it. Persistent cookies enable us to better understand how you interact with the Service and to until you delete it. Persistent cookies enable us to better understand how you interact with the Service and to
provide visitors with a better and more personalized experience by retaining information about their identity and provide visitors with a better and more personalized experience by retaining information about their identity and
preferences, including but not limited to keeping them logged in even if the browser is closed.</li> preferences, including but not limited to keeping them logged in even if the browser is closed.
</li>
</ul> </ul>
<p> <p>
If you do not want us to place a cookie on your device, you may be able to turn that feature off on your If you do not want us to place a cookie on your device, you may be able to turn that feature off on your
device. You may refuse to accept cookies from the Service at any time by activating the setting on your device. You may refuse to accept cookies from the Service at any time by activating the setting on your
browser which allows you to refuse cookies. Further information about the procedure to follow in order to browser which allows you to refuse cookies. Further information about the procedure to follow in order to
disable cookies can be found on your Internet browser providers website via your help screen. You may disable cookies can be found on your Internet browser providers website via your help screen. You may
wish to refer to <a href='http://www.allaboutcookies.org/manage-cookies/index.html' target='_blank'> wish to refer to <a
http://www.allaboutcookies.org/manage-cookies/index.html</a> for information on commonly used browsers. href="http://www.allaboutcookies.org/manage-cookies/index.html"
target="_blank"
>
http://www.allaboutcookies.org/manage-cookies/index.html</a> for information on commonly used browsers.
For more information about targeting and advertising cookies and how you can opt out, you can also visit For more information about targeting and advertising cookies and how you can opt out, you can also visit
<a href='http://optout.aboutads.info' target='_blank'>http://optout.aboutads.info</a>. Please be aware <a
href="http://optout.aboutads.info"
target="_blank"
>http://optout.aboutads.info</a>. Please be aware
that if cookies are disabled, not all features of the Service may operate properly or as intended. that if cookies are disabled, not all features of the Service may operate properly or as intended.
</p> </p>
<h3>Third-Party Analytics Providers</h3> <h3>Third-Party Analytics Providers</h3>
@@ -129,8 +164,18 @@
advised that if you opt out of any service, you may not be able to use the full functionality of the Service. advised that if you opt out of any service, you may not be able to use the full functionality of the Service.
</p> </p>
<ul> <ul>
<li>For Google Analytics, visit: <a href='https://marketingplatform.google.com/about/analytics/' target='_blank'>https://marketingplatform.google.com/about/analytics/</a></li> <li>
<li>For Amplitude, visit: <a href='https://amplitude.com/privacy' target='_blank'>https://amplitude.com/privacy</a></li> For Google Analytics, visit: <a
href="https://marketingplatform.google.com/about/analytics/"
target="_blank"
>https://marketingplatform.google.com/about/analytics/</a>
</li>
<li>
For Amplitude, visit: <a
href="https://amplitude.com/privacy"
target="_blank"
>https://amplitude.com/privacy</a>
</li>
</ul> </ul>
<h3>Third-Party Advertisers/Remarketers</h3> <h3>Third-Party Advertisers/Remarketers</h3>
<p> <p>
@@ -150,7 +195,9 @@
</p> </p>
<p> <p>
For more information on our advertising partner Google AdMob, please visit <a For more information on our advertising partner Google AdMob, please visit <a
href='https://policies.google.com/privacy?hl=en' target='_blank'>https://policies.google.com/privacy?hl=en</a>. href="https://policies.google.com/privacy?hl=en"
target="_blank"
>https://policies.google.com/privacy?hl=en</a>.
</p> </p>
<h3>Geolocation Information</h3> <h3>Geolocation Information</h3>
<p> <p>
@@ -229,7 +276,7 @@
</p> </p>
<p> <p>
You may opt out at any time from the use of your personal information for direct marketing purposes by You may opt out at any time from the use of your personal information for direct marketing purposes by
emailing the instructions to <a href='mailto:admin@habitica.com'>admin@habitica.com</a> or by clicking emailing the instructions to <a href="mailto:admin@habitica.com">admin@habitica.com</a> or by clicking
on the Unsubscribe link located on the bottom of any HabitRPG marketing email and following the on the Unsubscribe link located on the bottom of any HabitRPG marketing email and following the
instructions found on the page to which the link takes you. Please allow us a reasonable time to process instructions found on the page to which the link takes you. Please allow us a reasonable time to process
your request. You cannot opt out of receiving transactional e-mails related to the Service. your request. You cannot opt out of receiving transactional e-mails related to the Service.
@@ -274,7 +321,7 @@
direct marketing purposes during the preceding calendar year, including the names and addresses of those direct marketing purposes during the preceding calendar year, including the names and addresses of those
third parties, and examples of the types of Service or products marketed by those third parties. If you wish third parties, and examples of the types of Service or products marketed by those third parties. If you wish
to submit a request pursuant to Section 1798.83, please contact HabitRPG via email at to submit a request pursuant to Section 1798.83, please contact HabitRPG via email at
<a href='mailto:admin@habitica.com'>admin@habitica.com</a>. <a href="mailto:admin@habitica.com">admin@habitica.com</a>.
</p> </p>
<h2>NEVADA PRIVACY RIGHTS</h2> <h2>NEVADA PRIVACY RIGHTS</h2>
<p> <p>
@@ -291,7 +338,7 @@
<h2>LINKS TO EXTERNAL WEBSITES</h2> <h2>LINKS TO EXTERNAL WEBSITES</h2>
<p> <p>
The Service may contain links to third-party websites (<span style="text-decoration: underline;">External The Service may contain links to third-party websites (<span style="text-decoration: underline;">External
Sites</span>). HabitRPG has no control over the privacy practices or the content of any such External Sites. Sites</span>). HabitRPG has no control over the privacy practices or the content of any such External Sites.
As such, we are not responsible for the content or the privacy policies of such External Sites. You should As such, we are not responsible for the content or the privacy policies of such External Sites. You should
check the applicable privacy notice or privacy policy and terms of use when visiting any such External Sites. check the applicable privacy notice or privacy policy and terms of use when visiting any such External Sites.
</p> </p>
@@ -306,8 +353,8 @@
</p> </p>
<h2>HOW TO CONTACT US</h2> <h2>HOW TO CONTACT US</h2>
<p> <p>
If you have questions about this Privacy Notice, please e-mail us at <a href='mailto:admin@habitica.com'> If you have questions about this Privacy Notice, please e-mail us at <a href="mailto:admin@habitica.com">
admin@habitica.com</a> with Privacy Notice in the subject line. admin@habitica.com</a> with Privacy Notice in the subject line.
</p> </p>
<address> <address>
<strong>HabitRPG, Inc.</strong> <strong>HabitRPG, Inc.</strong>

View File

@@ -2,11 +2,20 @@
<!-- eslint-disable max-len --> <!-- eslint-disable max-len -->
<div class="container-fluid"> <div class="container-fluid">
<h1>Terms of Service</h1> <h1>Terms of Service</h1>
<p class="strong pagemeta">Last Updated: December 14, 2021</p> <p class="strong pagemeta">
Last Updated: December 14, 2021
</p>
<p>Thanks for choosing Habitica!</p> <p>Thanks for choosing Habitica!</p>
<p>Our Service is provided by HabitRPG, Inc. ("HabitRPG"). By accepting these Terms of Service and our Privacy Policy located at: <a href="https://habitica.com/static/privacy" target="_blank">https://habitica.com/static/privacy</a> (collectively, the "Agreement"), registering for the Service (as defined below), accessing or using any part of the Service, or otherwise manifesting your assent to the Agreement, you acknowledge that you have read, understood, and agree to be legally bound by the Agreement. If you do not agree to (or cannot comply with) the Agreement, you are not permitted to access or use the Service.</p> <p>
Our Service is provided by HabitRPG, Inc. ("HabitRPG"). By accepting these Terms of Service and our Privacy Policy located at: <a
href="https://habitica.com/static/privacy"
target="_blank"
>https://habitica.com/static/privacy</a> (collectively, the "Agreement"), registering for the Service (as defined below), accessing or using any part of the Service, or otherwise manifesting your assent to the Agreement, you acknowledge that you have read, understood, and agree to be legally bound by the Agreement. If you do not agree to (or cannot comply with) the Agreement, you are not permitted to access or use the Service.
</p>
<p>By accepting or agreeing to this Agreement on behalf of a company or other legal entity, you represent and warrant that you have the authority to bind that company or other legal entity to the Agreement and, in such event, "you" and "your" will refer and apply to that company or other legal entity.</p> <p>By accepting or agreeing to this Agreement on behalf of a company or other legal entity, you represent and warrant that you have the authority to bind that company or other legal entity to the Agreement and, in such event, "you" and "your" will refer and apply to that company or other legal entity.</p>
<p class="strong">THE SECTIONS BELOW TITLED "BINDING ARBITRATION," AND "CLASS ACTION WAIVER" CONTAIN A BINDING ARBITRATION AGREEMENT AND CLASS ACTION WAIVER. THEY AFFECT YOUR LEGAL RIGHTS. PLEASE READ THEM.</p> <p class="strong">
THE SECTIONS BELOW TITLED "BINDING ARBITRATION," AND "CLASS ACTION WAIVER" CONTAIN A BINDING ARBITRATION AGREEMENT AND CLASS ACTION WAIVER. THEY AFFECT YOUR LEGAL RIGHTS. PLEASE READ THEM.
</p>
<h2>Changes to the Terms of Service</h2> <h2>Changes to the Terms of Service</h2>
<p>These Terms of Service are effective as of the last updated date stated at the top of this page. We may change these Terms of Service from time to time with or without notice to you. By accessing the Service after we make any such changes to this Terms of Service, you are deemed to have accepted such changes. Please be aware that, to the extent permitted by applicable law, our use of the information collected is governed by the Terms of Service in effect at the time we collect the information. Please refer back to this Terms of Service on a regular basis.</p> <p>These Terms of Service are effective as of the last updated date stated at the top of this page. We may change these Terms of Service from time to time with or without notice to you. By accessing the Service after we make any such changes to this Terms of Service, you are deemed to have accepted such changes. Please be aware that, to the extent permitted by applicable law, our use of the information collected is governed by the Terms of Service in effect at the time we collect the information. Please refer back to this Terms of Service on a regular basis.</p>
<p>Our Service allows you to upload, store, send, download, or receive content, including but not limited to information, text, graphics, artwork, or other material ("Content"). You retain ownership of any intellectual property rights that you have in your Content. You hereby grant HabitRPG a worldwide, perpetual, irrevocable, sublicenseable, transferable, assignable, non-exclusive, and royalty-free right and license to use, reproduce, distribute, adapt, modify, translate, create derivative works of, publicly perform, publicly display, digitally perform, make, have made, sell, offer for sale, and import your Content, including all intellectual property rights therein. You represent, warrant, and agree that your Content does not and will not violate any third-party intellectual property, privacy, or other rights, and that you have all right, title and interest in and to your Content required to grant us the license above. We reserve the right at all times, but have no obligation, to delete or refuse to use or distribute any Content on or through the Service, including your Content.</p> <p>Our Service allows you to upload, store, send, download, or receive content, including but not limited to information, text, graphics, artwork, or other material ("Content"). You retain ownership of any intellectual property rights that you have in your Content. You hereby grant HabitRPG a worldwide, perpetual, irrevocable, sublicenseable, transferable, assignable, non-exclusive, and royalty-free right and license to use, reproduce, distribute, adapt, modify, translate, create derivative works of, publicly perform, publicly display, digitally perform, make, have made, sell, offer for sale, and import your Content, including all intellectual property rights therein. You represent, warrant, and agree that your Content does not and will not violate any third-party intellectual property, privacy, or other rights, and that you have all right, title and interest in and to your Content required to grant us the license above. We reserve the right at all times, but have no obligation, to delete or refuse to use or distribute any Content on or through the Service, including your Content.</p>
@@ -22,9 +31,9 @@
<p>HabitRPG reserves the right, in its sole discretion, to add, modify, or remove functionalities or features from the Service, and improve, change and/or update the Service. We may also suspend or terminate the Service at any time, with or without notice to you.</p> <p>HabitRPG reserves the right, in its sole discretion, to add, modify, or remove functionalities or features from the Service, and improve, change and/or update the Service. We may also suspend or terminate the Service at any time, with or without notice to you.</p>
<p>You can choose to stop using our Service at any time. We may suspend or cease providing the Service to you at any time, including if we determine in our sole discretion, that:</p> <p>You can choose to stop using our Service at any time. We may suspend or cease providing the Service to you at any time, including if we determine in our sole discretion, that:</p>
<ul> <ul>
<li>You have violated any part of this Agreement, the Privacy Policy, or the Community Guidelines;</li> <li>You have violated any part of this Agreement, the Privacy Policy, or the Community Guidelines;</li>
<li>We have stopped offering the Service in your region; or</li> <li>We have stopped offering the Service in your region; or</li>
<li>Doing so would be in the best interests of our community, the Service, or the rights of a third party.</li> <li>Doing so would be in the best interests of our community, the Service, or the rights of a third party.</li>
</ul> </ul>
<p>If your account is terminated, you will no longer have access to it, including to any of the associated data or Content. You will not be entitled to any refunds and we will have no liability to you. We also reserve the right to terminate any other accounts you may have created, as well as access to any other HabitRPG Service (also without refunds or liability to you).</p> <p>If your account is terminated, you will no longer have access to it, including to any of the associated data or Content. You will not be entitled to any refunds and we will have no liability to you. We also reserve the right to terminate any other accounts you may have created, as well as access to any other HabitRPG Service (also without refunds or liability to you).</p>
<p>You understand and agree that using the Service comes with the risk that your account may be terminated or suspended at our discretion and at any time. Please keep this risk in mind and comport yourself appropriately.</p> <p>You understand and agree that using the Service comes with the risk that your account may be terminated or suspended at our discretion and at any time. Please keep this risk in mind and comport yourself appropriately.</p>
@@ -35,31 +44,36 @@
<p>Using our Service does not grant you ownership of any intellectual property rights in our Service or the content you may have access to. You may not use any copyrighted content in our Service unless you obtain permission from the content owner and/or are otherwise permitted by law. The Terms do not grant you the right to use any branding or logos used in our Service. Our Service may display some logos, trademarks, or branding materials that are not the property of HabitRPG. Such content is the sole responsibility of the entity that makes it available.</p> <p>Using our Service does not grant you ownership of any intellectual property rights in our Service or the content you may have access to. You may not use any copyrighted content in our Service unless you obtain permission from the content owner and/or are otherwise permitted by law. The Terms do not grant you the right to use any branding or logos used in our Service. Our Service may display some logos, trademarks, or branding materials that are not the property of HabitRPG. Such content is the sole responsibility of the entity that makes it available.</p>
<p>You may not abuse and/or misuse our Service, including but not limited to the following actions:</p> <p>You may not abuse and/or misuse our Service, including but not limited to the following actions:</p>
<ul> <ul>
<li>Using the Service for any unlawful purposes or activities;</li> <li>Using the Service for any unlawful purposes or activities;</li>
<li>Uploading any content to the Service in violation of any applicable law, including but not limited to intellectual property laws and publicity laws;</li> <li>Uploading any content to the Service in violation of any applicable law, including but not limited to intellectual property laws and publicity laws;</li>
<li>Sending unsolicited promotions or advertisements;</li> <li>Sending unsolicited promotions or advertisements;</li>
<li>Accessing or tampering with the Service's server systems;</li> <li>Accessing or tampering with the Service's server systems;</li>
<li>Interfering with or disrupting the access of any user, host, or network;</li> <li>Interfering with or disrupting the access of any user, host, or network;</li>
<li>Abusing or submitting excessively frequent requests to the Service via the API</li> <li>Abusing or submitting excessively frequent requests to the Service via the API</li>
<li>Spamming chat, whether for personal or commercial purposes, by disrupting the flow of conversation with repeated postings;</li> <li>Spamming chat, whether for personal or commercial purposes, by disrupting the flow of conversation with repeated postings;</li>
<li>Impersonating any person, business, or entity, including an employee of HabitRPG, or member of the Habitica moderation team, or communicating in any way that makes it appear that the communication originates from Habitica staff or HabitRPG;</li> <li>Impersonating any person, business, or entity, including an employee of HabitRPG, or member of the Habitica moderation team, or communicating in any way that makes it appear that the communication originates from Habitica staff or HabitRPG;</li>
<li>Transmitting or communicating any content which, in the sole and exclusive discretion of HabitRPG, is deemed offensive, including language that is unlawful, harmful, threatening, abusive, harassing, defamatory, vulgar, obscene, sexually explicit, or racially, ethically, or otherwise objectionable,</li> <li>Transmitting or communicating any content which, in the sole and exclusive discretion of HabitRPG, is deemed offensive, including language that is unlawful, harmful, threatening, abusive, harassing, defamatory, vulgar, obscene, sexually explicit, or racially, ethically, or otherwise objectionable,</li>
<li>Participating in any action which, in the sole and exclusive judgment of HabitRPG, defrauds any other user of the Game, including by scamming or social engineering; or</li> <li>Participating in any action which, in the sole and exclusive judgment of HabitRPG, defrauds any other user of the Game, including by scamming or social engineering; or</li>
<li>Inducing or encouraging others to violate the Community Guidelines or the Agreement.</li> <li>Inducing or encouraging others to violate the Community Guidelines or the Agreement.</li>
</ul> </ul>
<p>HabitRPG, in its sole discretion, will determine what constitutes abuse and/or misuse of our Service.</p> <p>HabitRPG, in its sole discretion, will determine what constitutes abuse and/or misuse of our Service.</p>
<h2>Premium Service and Payments</h2> <h2>Premium Service and Payments</h2>
<p>You may choose our free Service or paid Service ("Premium") depending on your needs. We do not guarantee when, if ever, Premium features will be available in the free Service. You may upgrade from free Service to Premium at any time by any of the following methods:</p> <p>You may choose our free Service or paid Service ("Premium") depending on your needs. We do not guarantee when, if ever, Premium features will be available in the free Service. You may upgrade from free Service to Premium at any time by any of the following methods:</p>
<ul> <ul>
<li>Web: Selecting the user icon in the top right corner and selecting "Subscription" from the dropdown menu,</li> <li>Web: Selecting the user icon in the top right corner and selecting "Subscription" from the dropdown menu,</li>
<li>Web: Clicking the green gem icon in the navigation bar at the top of the screen and following instructions to Subscribe or Buy Gems,</li> <li>Web: Clicking the green gem icon in the navigation bar at the top of the screen and following instructions to Subscribe or Buy Gems,</li>
<li>Android: Tap the menu icon in the top left corner of the main screen and select "Gems & Subscription". Follow the instructions to make a purchase.</li> <li>Android: Tap the menu icon in the top left corner of the main screen and select "Gems & Subscription". Follow the instructions to make a purchase.</li>
<li>iOS: Tap the menu icon in the lower right and select "Gems & Subscriptions". Follow the instructions to make a purchase.</li> <li>iOS: Tap the menu icon in the lower right and select "Gems & Subscriptions". Follow the instructions to make a purchase.</li>
</ul> </ul>
<p>You will be charged the amount shown on Pricing before you can access Premium Service. All prices shown on Pricing are inclusive of any applicable sales taxes, levies, value-added taxes, or duties imposed by taxing authorities, and you are responsible for payment of all such taxes, levies, or duties. We may revise the Pricing at any time and may, from time to time, modify, amend, or supplement our fees and fee-billing methods. Such changes shall be effective upon posting on the Pricing page or elsewhere in the Service. If there is a dispute regarding payment of fees to us, we reserve the right to terminate or suspend your account at our sole discretion.</p> <p>You will be charged the amount shown on Pricing before you can access Premium Service. All prices shown on Pricing are inclusive of any applicable sales taxes, levies, value-added taxes, or duties imposed by taxing authorities, and you are responsible for payment of all such taxes, levies, or duties. We may revise the Pricing at any time and may, from time to time, modify, amend, or supplement our fees and fee-billing methods. Such changes shall be effective upon posting on the Pricing page or elsewhere in the Service. If there is a dispute regarding payment of fees to us, we reserve the right to terminate or suspend your account at our sole discretion.</p>
<p>BY PURCHASING PREMIUM YOU EXPRESSLY UNDERSTAND AND AGREE TO OUR REFUND POLICY:</p> <p>BY PURCHASING PREMIUM YOU EXPRESSLY UNDERSTAND AND AGREE TO OUR REFUND POLICY:</p>
<p>WITHIN THIRTY (30) DAYS OF YOUR PREMIUM PAYMENT DATE AS SHOWN ON YOUR PAYMENT BILL, YOU CAN REQUEST A FULL REFUND BY CONTACTING US AT ADMIN@HABITICA.COM. AFTER THIRTY (30) DAYS OF YOUR PREMIUM PAYMENT DATE, ANY PAYMENT REFUND IS SOLELY SUBJECT TO OUR DISCRETION. THE REFUND SHALL BE YOUR SOLE AND EXCLUSIVE REMEDY.</p> <p>WITHIN THIRTY (30) DAYS OF YOUR PREMIUM PAYMENT DATE AS SHOWN ON YOUR PAYMENT BILL, YOU CAN REQUEST A FULL REFUND BY CONTACTING US AT ADMIN@HABITICA.COM. AFTER THIRTY (30) DAYS OF YOUR PREMIUM PAYMENT DATE, ANY PAYMENT REFUND IS SOLELY SUBJECT TO OUR DISCRETION. THE REFUND SHALL BE YOUR SOLE AND EXCLUSIVE REMEDY.</p>
<p>FOR ANY CUSTOMER WHO PURCHASED PREMIUM IN APPLE INC.'s APP STORE ("APP STORE"), PLEASE CONTACT APPLE INC.'s SUPPORT TEAM: <a href="http://reportaproblem.apple.com" target="_blank">http://reportaproblem.apple.com</a>. APPLE'S APP STORE DOES NOT ALLOW DEVELOPERS TO ISSUE REFUND FOR APP STORE PURCHASES MADE BY CUSTOMERS.</p> <p>
FOR ANY CUSTOMER WHO PURCHASED PREMIUM IN APPLE INC.'s APP STORE ("APP STORE"), PLEASE CONTACT APPLE INC.'s SUPPORT TEAM: <a
href="http://reportaproblem.apple.com"
target="_blank"
>http://reportaproblem.apple.com</a>. APPLE'S APP STORE DOES NOT ALLOW DEVELOPERS TO ISSUE REFUND FOR APP STORE PURCHASES MADE BY CUSTOMERS.
</p>
<h2>Warranty Disclaimer</h2> <h2>Warranty Disclaimer</h2>
<p>THE SERVICE AND ANY CONTENT MADE AVAILABLE BY HABITRPG VIA THE SERVICE IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT ANY WARRANTIES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, THAT THE SERVICE OR CONTENT WILL OPERATE ERROR-FREE OR THAT THE SERVICE OR CONTENT OR ITS SERVERS ARE FREE OF COMPUTER VIRUSES OR SIMILAR CONTAMINATION OR DESTRUCTIVE FEATURES.</p> <p>THE SERVICE AND ANY CONTENT MADE AVAILABLE BY HABITRPG VIA THE SERVICE IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT ANY WARRANTIES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, THAT THE SERVICE OR CONTENT WILL OPERATE ERROR-FREE OR THAT THE SERVICE OR CONTENT OR ITS SERVERS ARE FREE OF COMPUTER VIRUSES OR SIMILAR CONTAMINATION OR DESTRUCTIVE FEATURES.</p>
<p>WE DISCLAIM ALL WARRANTIES, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF TITLE, MERCHANTABILITY, NON-INFRINGEMENT OF THIRD PARTIES' RIGHTS, AND FITNESS FOR PARTICULAR PURPOSE AND ANY WARRANTIES ARISING FROM A COURSE OF DEALING, COURSE OF PERFORMANCE, OR USAGE OF TRADE.</p> <p>WE DISCLAIM ALL WARRANTIES, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF TITLE, MERCHANTABILITY, NON-INFRINGEMENT OF THIRD PARTIES' RIGHTS, AND FITNESS FOR PARTICULAR PURPOSE AND ANY WARRANTIES ARISING FROM A COURSE OF DEALING, COURSE OF PERFORMANCE, OR USAGE OF TRADE.</p>
@@ -71,7 +85,12 @@
<h2>Compliance with Applicable Laws</h2> <h2>Compliance with Applicable Laws</h2>
<p>The Service is based in the United States. We make no claims concerning whether the Service or posted content may be downloaded, viewed, or be appropriate for use outside of the United States. If you access the Service or such content from outside of the United States, you do so at your own risk. Whether inside or outside of the United States, you are solely responsible for ensuring compliance with the laws of your specific jurisdiction.</p> <p>The Service is based in the United States. We make no claims concerning whether the Service or posted content may be downloaded, viewed, or be appropriate for use outside of the United States. If you access the Service or such content from outside of the United States, you do so at your own risk. Whether inside or outside of the United States, you are solely responsible for ensuring compliance with the laws of your specific jurisdiction.</p>
<h2>Binding Arbitration</h2> <h2>Binding Arbitration</h2>
<p>In the event of a dispute arising under or relating to this Agreement or the Service (each, a "<u>Dispute</u>"), such dispute will be finally and exclusively resolved by binding arbitration governed by the Federal Arbitration Act ("<u>FAA</u>"). Any election to arbitrate, at any time, shall be final and binding on the other party. NEITHER PARTY SHALL HAVE THE RIGHT TO LITIGATE SUCH CLAIM IN COURT OR TO HAVE A JURY TRIAL, EXCEPT EITHER PARTY MAY BRING ITS CLAIM IN ITS LOCAL SMALL CLAIMS COURT, IF PERMITTED BY THAT SMALL CLAIMS COURT RULES AND IF WITHIN SUCH COURT'S JURISDICTION. ARBITRATION IS DIFFERENT FROM COURT, AND DISCOVERY AND APPEAL RIGHTS MAY ALSO BE LIMITED IN ARBITRATION. All disputes will be resolved before a neutral arbitrator selected jointly by the parties, whose decision will be final, except for a limited right of appeal under the FAA. The arbitration shall be commenced and conducted by JAMS pursuant to its then current Comprehensive Arbitration Rules and Procedures and in accordance with the Expedited Procedures in those rules, or, where appropriate, pursuant to JAMS' Streamlined Arbitration Rules and Procedures. All applicable JAMS' rules and procedures are available at the JAMS website <a href="https://www.jamsadr.com" target="_blank">www.jamsadr.com</a>. Each party will be responsible for paying any JAMS filing, administrative, and arbitrator fees in accordance with JAMS rules. Judgment on the arbitrator's award may be entered in any court having jurisdiction. This clause shall not preclude parties from seeking provisional remedies in aid of arbitration from a court of appropriate jurisdiction. The arbitration may be conducted in person, through the submission of documents, by phone, or online. If conducted in person, the arbitration shall take place in the United States county where you reside. The parties may litigate in court to compel arbitration, to stay a proceeding pending arbitration, or to confirm, modify, vacate, or enter judgment on the award entered by the arbitrator. The parties shall cooperate in good faith in the voluntary and informal exchange of all non-privileged documents and other information (including electronically stored information) relevant to the Dispute immediately after commencement of the arbitration. As set forth below, nothing in this Agreement will prevent us from seeking injunctive relief in any court of competent jurisdiction as necessary to protect our proprietary interests.</p> <p>
In the event of a dispute arising under or relating to this Agreement or the Service (each, a "<u>Dispute</u>"), such dispute will be finally and exclusively resolved by binding arbitration governed by the Federal Arbitration Act ("<u>FAA</u>"). Any election to arbitrate, at any time, shall be final and binding on the other party. NEITHER PARTY SHALL HAVE THE RIGHT TO LITIGATE SUCH CLAIM IN COURT OR TO HAVE A JURY TRIAL, EXCEPT EITHER PARTY MAY BRING ITS CLAIM IN ITS LOCAL SMALL CLAIMS COURT, IF PERMITTED BY THAT SMALL CLAIMS COURT RULES AND IF WITHIN SUCH COURT'S JURISDICTION. ARBITRATION IS DIFFERENT FROM COURT, AND DISCOVERY AND APPEAL RIGHTS MAY ALSO BE LIMITED IN ARBITRATION. All disputes will be resolved before a neutral arbitrator selected jointly by the parties, whose decision will be final, except for a limited right of appeal under the FAA. The arbitration shall be commenced and conducted by JAMS pursuant to its then current Comprehensive Arbitration Rules and Procedures and in accordance with the Expedited Procedures in those rules, or, where appropriate, pursuant to JAMS' Streamlined Arbitration Rules and Procedures. All applicable JAMS' rules and procedures are available at the JAMS website <a
href="https://www.jamsadr.com"
target="_blank"
>www.jamsadr.com</a>. Each party will be responsible for paying any JAMS filing, administrative, and arbitrator fees in accordance with JAMS rules. Judgment on the arbitrator's award may be entered in any court having jurisdiction. This clause shall not preclude parties from seeking provisional remedies in aid of arbitration from a court of appropriate jurisdiction. The arbitration may be conducted in person, through the submission of documents, by phone, or online. If conducted in person, the arbitration shall take place in the United States county where you reside. The parties may litigate in court to compel arbitration, to stay a proceeding pending arbitration, or to confirm, modify, vacate, or enter judgment on the award entered by the arbitrator. The parties shall cooperate in good faith in the voluntary and informal exchange of all non-privileged documents and other information (including electronically stored information) relevant to the Dispute immediately after commencement of the arbitration. As set forth below, nothing in this Agreement will prevent us from seeking injunctive relief in any court of competent jurisdiction as necessary to protect our proprietary interests.
</p>
<p>ANY CLAIMS, ACTIONS OR PROCEEDINGS BY YOU MUST BE COMMENCED WITHIN ONE YEAR AFTER THE EVENT THAT GAVE RISE TO YOUR CLAIM OCCURS. ALL OTHER CLAIMS YOU MAY HAVE ARE PERMANENTLY BARRED.</p> <p>ANY CLAIMS, ACTIONS OR PROCEEDINGS BY YOU MUST BE COMMENCED WITHIN ONE YEAR AFTER THE EVENT THAT GAVE RISE TO YOUR CLAIM OCCURS. ALL OTHER CLAIMS YOU MAY HAVE ARE PERMANENTLY BARRED.</p>
<h2>Class Action Waiver</h2> <h2>Class Action Waiver</h2>
<p>You agree that any arbitration or proceeding shall be limited to the Dispute between us and you individually. To the full extent permitted by law, (i) no arbitration or proceeding shall be joined with any other; (ii) there is no right or authority for any Dispute to be arbitrated or resolved on a class action-basis or to utilize class action procedures; and (iii) there is no right or authority for any Dispute to be brought in a purported representative capacity on behalf of the general public or any other persons. YOU AGREE THAT YOU MAY BRING CLAIMS AGAINST US ONLY IN YOUR INDIVIDUAL CAPACITY AND NOT AS A PLAINTIFF OR CLASS MEMBER IN ANY PURPORTED CLASS OR REPRESENTATIVE PROCEEDING.</p> <p>You agree that any arbitration or proceeding shall be limited to the Dispute between us and you individually. To the full extent permitted by law, (i) no arbitration or proceeding shall be joined with any other; (ii) there is no right or authority for any Dispute to be arbitrated or resolved on a class action-basis or to utilize class action procedures; and (iii) there is no right or authority for any Dispute to be brought in a purported representative capacity on behalf of the general public or any other persons. YOU AGREE THAT YOU MAY BRING CLAIMS AGAINST US ONLY IN YOUR INDIVIDUAL CAPACITY AND NOT AS A PLAINTIFF OR CLASS MEMBER IN ANY PURPORTED CLASS OR REPRESENTATIVE PROCEEDING.</p>

View File

@@ -90,6 +90,7 @@
"addedLocalAuth": "Successfully added local authentication", "addedLocalAuth": "Successfully added local authentication",
"data": "Δεδομένα", "data": "Δεδομένα",
"email": "Email", "email": "Email",
"emailOrUsername": "Username or Email",
"registerWithSocial": "Register with <%= network %>", "registerWithSocial": "Register with <%= network %>",
"registeredWithSocial": "Registered with <%= network %>", "registeredWithSocial": "Registered with <%= network %>",
"emailNotifications": "Ειδοποιήσεις email", "emailNotifications": "Ειδοποιήσεις email",

View File

@@ -12,7 +12,7 @@
"companyDonate": "Donate", "companyDonate": "Donate",
"forgotPassword": "Forgot Password?", "forgotPassword": "Forgot Password?",
"emailNewPass": "Email a Password Reset Link", "emailNewPass": "Email a Password Reset Link",
"forgotPasswordSteps": "Enter the email address you used to register your Habitica account.", "forgotPasswordSteps": "Enter your username or the email address you used to register your Habitica account.",
"sendLink": "Send Link", "sendLink": "Send Link",
"footerDevs": "Developers", "footerDevs": "Developers",
"footerCommunity": "Community", "footerCommunity": "Community",
@@ -125,7 +125,7 @@
"passwordConfirmationMatch": "Password confirmation doesn't match password.", "passwordConfirmationMatch": "Password confirmation doesn't match password.",
"minPasswordLength": "Password must be 8 characters or more.", "minPasswordLength": "Password must be 8 characters or more.",
"passwordResetPage": "Reset Password", "passwordResetPage": "Reset Password",
"passwordReset": "If we have your email on file, instructions for setting a new password have been sent to your email.", "passwordReset": "If we have your email or username on file, instructions for setting a new password have been sent to your email.",
"invalidLoginCredentialsLong": "Uh-oh - your email address / username or password is incorrect.\n- Make sure they are typed correctly. Your username and password are case-sensitive.\n- You may have signed up with Facebook or Google-sign-in, not email so double-check by trying them.\n- If you forgot your password, click \"Forgot Password\".", "invalidLoginCredentialsLong": "Uh-oh - your email address / username or password is incorrect.\n- Make sure they are typed correctly. Your username and password are case-sensitive.\n- You may have signed up with Facebook or Google-sign-in, not email so double-check by trying them.\n- If you forgot your password, click \"Forgot Password\".",
"invalidCredentials": "There is no account that uses those credentials.", "invalidCredentials": "There is no account that uses those credentials.",
"accountSuspended": "This account, User ID \"<%= userId %>\", has been blocked for breaking the Community Guidelines (https://habitica.com/static/community-guidelines) or Terms of Service (https://habitica.com/static/terms). For details or to ask to be unblocked, please email our Community Manager at <%= communityManagerEmail %> or ask your parent or guardian to email them. Please include your @Username in the email.", "accountSuspended": "This account, User ID \"<%= userId %>\", has been blocked for breaking the Community Guidelines (https://habitica.com/static/community-guidelines) or Terms of Service (https://habitica.com/static/terms). For details or to ask to be unblocked, please email our Community Manager at <%= communityManagerEmail %> or ask your parent or guardian to email them. Please include your @Username in the email.",
@@ -143,7 +143,8 @@
"confirmPassword": "Confirm Password", "confirmPassword": "Confirm Password",
"usernameLimitations": "Username must be 1 to 20 characters, containing only letters a to z, numbers 0 to 9, hyphens, or underscores, and cannot include any inappropriate terms.", "usernameLimitations": "Username must be 1 to 20 characters, containing only letters a to z, numbers 0 to 9, hyphens, or underscores, and cannot include any inappropriate terms.",
"usernamePlaceholder": "e.g., HabitRabbit", "usernamePlaceholder": "e.g., HabitRabbit",
"emailPlaceholder": "e.g., rabbit@example.com", "emailPlaceholder": "e.g., gryphon@example.com",
"emailUsernamePlaceholder": "e.g., habitrabbit or gryphon@example.com",
"passwordPlaceholder": "e.g., ******************", "passwordPlaceholder": "e.g., ******************",
"confirmPasswordPlaceholder": "Make sure it's the same password!", "confirmPasswordPlaceholder": "Make sure it's the same password!",
"joinHabitica": "Join Habitica", "joinHabitica": "Join Habitica",

View File

@@ -134,6 +134,7 @@
"saveCustomDayStart": "Save Custom Day Start", "saveCustomDayStart": "Save Custom Day Start",
"registration": "Registration", "registration": "Registration",
"addLocalAuth": "Add Email and Password Login", "addLocalAuth": "Add Email and Password Login",
"addPasswordAuth": "Add Password",
"generateCodes": "Generate Codes", "generateCodes": "Generate Codes",
"generate": "Generate", "generate": "Generate",
"getCodes": "Get Codes", "getCodes": "Get Codes",

View File

@@ -341,7 +341,15 @@ api.resetPassword = {
if (validationErrors) throw validationErrors; if (validationErrors) throw validationErrors;
const email = req.body.email.toLowerCase(); const email = req.body.email.toLowerCase();
const user = await User.findOne({ 'auth.local.email': email }).exec(); const user = await User.findOne({
$or: [
{ 'auth.local.username': email.replace(/^@/, '') },
{ 'auth.local.email': email },
{ 'auth.apple.emails.value': email },
{ 'auth.google.emails.value': email },
{ 'auth.facebook.emails.value': email },
],
}).exec();
if (user) { if (user) {
// create an encrypted link to be used to reset the password // create an encrypted link to be used to reset the password
@@ -385,7 +393,9 @@ api.updateEmail = {
if (!user.auth.local.email) throw new BadRequest(res.t('userHasNoLocalRegistration')); if (!user.auth.local.email) throw new BadRequest(res.t('userHasNoLocalRegistration'));
req.checkBody('newEmail', res.t('newEmailRequired')).notEmpty().isEmail(); req.checkBody('newEmail', res.t('newEmailRequired')).notEmpty().isEmail();
req.checkBody('password', res.t('missingPassword')).notEmpty(); if (user.auth.local.hashed_password) {
req.checkBody('password', res.t('missingPassword')).notEmpty();
}
const validationErrors = req.validationErrors(); const validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors; if (validationErrors) throw validationErrors;
@@ -395,13 +405,15 @@ api.updateEmail = {
if (emailAlreadyInUse) throw new NotAuthorized(res.t('cannotFulfillReq', { techAssistanceEmail: TECH_ASSISTANCE_EMAIL })); if (emailAlreadyInUse) throw new NotAuthorized(res.t('cannotFulfillReq', { techAssistanceEmail: TECH_ASSISTANCE_EMAIL }));
const { password } = req.body; if (user.auth.local.hashed_password) {
const isValidPassword = await passwordUtils.compare(user, password); const { password } = req.body;
if (!isValidPassword) throw new NotAuthorized(res.t('wrongPassword')); const isValidPassword = await passwordUtils.compare(user, password);
if (!isValidPassword) throw new NotAuthorized(res.t('wrongPassword'));
// if password is using old sha1 encryption, change it // if password is using old sha1 encryption, change it
if (user.auth.local.passwordHashMethod === 'sha1') { if (user.auth.local.passwordHashMethod === 'sha1') {
await passwordUtils.convertToBcrypt(user, password); await passwordUtils.convertToBcrypt(user, password);
}
} }
user.auth.local.email = req.body.newEmail.toLowerCase(); user.auth.local.email = req.body.newEmail.toLowerCase();

View File

@@ -128,12 +128,13 @@ async function registerLocal (req, res, { isV3 = false }) {
}, { 'auth.local': 1 }).exec(); }, { 'auth.local': 1 }).exec();
if (user) { if (user) {
if (email === user.auth.local.email) throw new NotAuthorized(res.t('emailTaken'));
// Check that the lowercase username isn't already used
if (existingUser) { if (existingUser) {
if (email === user.auth.local.email && existingUser._id !== user._id) throw new NotAuthorized(res.t('emailTaken'));
if (lowerCaseUsername === user.auth.local.lowerCaseUsername && existingUser._id !== user._id) throw new NotAuthorized(res.t('usernameTaken')); if (lowerCaseUsername === user.auth.local.lowerCaseUsername && existingUser._id !== user._id) throw new NotAuthorized(res.t('usernameTaken'));
} else if (lowerCaseUsername === user.auth.local.lowerCaseUsername) { } else if (lowerCaseUsername === user.auth.local.lowerCaseUsername) {
throw new NotAuthorized(res.t('usernameTaken')); throw new NotAuthorized(res.t('usernameTaken'));
} else {
throw new NotAuthorized(res.t('emailTaken'));
} }
} }

View File

@@ -88,8 +88,8 @@ export async function validatePasswordResetCodeAndFindUser (code) {
if (isCodeValid) { if (isCodeValid) {
user = await User.findById(userId).exec(); user = await User.findById(userId).exec();
// check if user is found and if it's an email & password account // check if user is found
if (!user || !user.auth || !user.auth.local || !user.auth.local.email) { if (!user) {
isCodeValid = false; isCodeValid = false;
} else if (code !== user.auth.local.passwordResetCode) { } else if (code !== user.auth.local.passwordResetCode) {
// Make sure only the last code can be used // Make sure only the last code can be used

View File

@@ -38,6 +38,12 @@ schema.plugin(baseModel, {
plainObj.flags.newStuff = originalDoc.checkNewStuff(); plainObj.flags.newStuff = originalDoc.checkNewStuff();
} }
if (plainObj.auth && plainObj.auth.local && originalDoc.auth.local.hashed_password) {
plainObj.auth.local.has_password = true;
} else if (plainObj.auth && plainObj.auth.local && originalDoc.auth.local.email) {
plainObj.auth.local.has_password = false;
}
return plainObj; return plainObj;
}, },
}); });