diff --git a/backend/.env.example b/backend/.env.example index 50405affa..873912f28 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -95,3 +95,6 @@ REDIS_PASSWORD # In minutes, the time a cached remote event will expire at. REDIS_EVENT_EXPIRE_TIME=15 + +TBA_PRIVACY_POLICY_URL= +TBA_TERMS_OF_USE_URL= diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 000000000..4f1b28d2d --- /dev/null +++ b/backend/README.md @@ -0,0 +1,43 @@ +# Thunderbird Appointment Backend + +This is the backend component of Thunderbird Appointment written in Python using FastAPI, SQLAlchemy, and pytest. + +## Installation / Running + +### Development + +A docker file with instructions is provided for development use, please check [appointment/readme.md](../README.md) for more information. + +### Self-hosting + +More information will be provided in the future. There is currently a docker file provided which we use to deploy to AWS' ECS which should help you get started. + +## Configuration + +The backend project uses dotenv files to inject environment variables into the application. A starting template can be found as [.env.example](.env.example). Copy that as your .env to get started. + +You will want to ensure any variable ending with `_SECRET` has a secret value assigned. Additionally there are values such as SMTP settings for mail, google authentication credentials for google oauth flow with the google calendar api, and zoom api credentials available. + +### Authentication + +This project is deployed with Mozilla Accounts (known as fxa in the code.) Since Mozilla Accounts is for internal use you will need to use password authentication. Note: password authentication does not currently have a registration flow. + +## Commands + +Backend has a light selection of cli commands available to be run inside a container. + +``` +run-command main --help + Usage: run-command main [OPTIONS] COMMAND [ARGS]... + +╭─ Options ──────────────────────────────────────────────────────╮ +│ --help Show this message and exit. │ +╰────────────────────────────────────────────────────────────────╯ +╭─ Commands ─────────────────────────────────────────────────────╮ +│ download-legal │ +│ update-db │ +╰────────────────────────────────────────────────────────────────╯ +``` + +* Download-legal is an internal command to process privacy policy and terms of service files that will be served by the frontend. +* Update-db runs on docker container entry, and ensures the latest db migration has run, or if it's a new db then to kickstart that. diff --git a/backend/requirements.txt b/backend/requirements.txt index 5a8e2f545..fe14fbdae 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -14,6 +14,8 @@ google-auth-oauthlib==1.0.0 jinja2==3.1.3 icalendar==5.0.4 itsdangerous==2.1.2 +markdown==3.6 +MarkupSafe==2.1.2 python-dotenv==1.0.0 python-jose==3.3.0 python-multipart==0.0.7 diff --git a/backend/src/appointment/commands/download_legal.py b/backend/src/appointment/commands/download_legal.py new file mode 100644 index 000000000..bfea47b92 --- /dev/null +++ b/backend/src/appointment/commands/download_legal.py @@ -0,0 +1,38 @@ +import os + +import markupsafe +import requests +import markdown + + +def run(): + """Helper function to update privacy and terms. Please check to ensure you're not getting a 404 before committing lol.""" + print("Downloading the latest legal documents...") + + extensions = ['markdown.extensions.attr_list'] + # Only english for now. There's no german TB privacy policy? + locales = ['en'] + + for locale in locales: + privacy_policy = os.getenv('TBA_PRIVACY_POLICY_URL').format(locale=locale) + terms_of_use = os.getenv('TBA_TERMS_OF_USE_URL').format(locale=locale) + + os.makedirs(f'{os.path.dirname(__file__)}/../tmp/legal/{locale}', exist_ok=True) + + if privacy_policy: + print("Privacy policy url found.") + contents = requests.get(privacy_policy).text + html = markupsafe.Markup(markdown.markdown(contents, extensions=extensions)) + + with open(f'{os.path.dirname(__file__)}/../tmp/legal/{locale}/privacy.html', 'w') as fh: + fh.write(html) + + if terms_of_use: + print("Terms of use url found.") + contents = requests.get(terms_of_use).text + html = markupsafe.Markup(markdown.markdown(contents, extensions=extensions)) + + with open(f'{os.path.dirname(__file__)}/../tmp/legal/{locale}/terms.html', 'w') as fh: + fh.write(html) + + print("Done! Copy them over to the frontend/src/assets/legal!") diff --git a/backend/src/appointment/routes/api.py b/backend/src/appointment/routes/api.py index 9ce708a96..f490ed355 100644 --- a/backend/src/appointment/routes/api.py +++ b/backend/src/appointment/routes/api.py @@ -11,6 +11,7 @@ # database from sqlalchemy.orm import Session +from starlette.responses import HTMLResponse from .. import utils from ..database import repo, schemas @@ -584,3 +585,17 @@ def send_feedback( details=form_data.details, ) return True + + +@router.get('/privacy') +def privacy(): + with open(f'{os.path.dirname(__file__)}/../templates/legal/en/privacy.jinja2') as fh: + contents = fh.read() + return HTMLResponse(contents) + + +@router.get('/terms') +def terms(): + with open(f'{os.path.dirname(__file__)}/../templates/legal/en/terms.jinja2') as fh: + contents = fh.read() + return HTMLResponse(contents) diff --git a/backend/src/appointment/routes/commands.py b/backend/src/appointment/routes/commands.py index 61b549ccb..b68103020 100644 --- a/backend/src/appointment/routes/commands.py +++ b/backend/src/appointment/routes/commands.py @@ -3,7 +3,7 @@ import os import typer -from ..commands import update_db +from ..commands import update_db, download_legal router = typer.Typer() @@ -29,3 +29,7 @@ def cron_lock(lock_name): def update_database(): update_db.run() + +@router.command('download-legal') +def download_legal_docs(): + download_legal.run() diff --git a/backend/src/appointment/tmp/.gitignore b/backend/src/appointment/tmp/.gitignore index 933daa684..fa091dd85 100644 --- a/backend/src/appointment/tmp/.gitignore +++ b/backend/src/appointment/tmp/.gitignore @@ -1 +1,2 @@ *.json +*.html diff --git a/frontend/src/assets/legal/en/privacy.html b/frontend/src/assets/legal/en/privacy.html new file mode 100644 index 000000000..7a6f3937d --- /dev/null +++ b/frontend/src/assets/legal/en/privacy.html @@ -0,0 +1,44 @@ +

Thunderbird Privacy Notice

+

Last updated March 21, 2024

+

The Thunderbird application allows users to privately integrate and manage their online communications.

+

This Privacy Notice explains what data Thunderbird collects and shares, and why. We also adhere to the Mozilla Privacy Policy for how we receive, handle, and share information.

+

Thunderbird Collects Data To:

+

Improve Performance and Stability For Our Users

+

Thunderbird collects telemetry data by default to help improve the performance and stability of Thunderbird. There are two types of telemetry data: interaction data and technical data.

+

Interaction data: Thunderbird receives data about your interactions with the application, such as whether calendars and filters are being used, and how many email accounts a user has.

+

Technical data: Thunderbird also receives basic information about your device and application version, including, hardware configuration, device operating system, and language preference. When Thunderbird sends technical data to us, your IP address is temporarily collected as part of our server logs.

+

Read the telemetry documentation and learn how to opt-out of this data collection here.

+

Set-Up and Configure Your Email

+

Thunderbird collects your email domain and other technical data to set-up and configure your email account. Other information, like your name, your email messages, and your account’s address book are stored locally on your computer and never sent to us. Learn more here.

+

Email domain: Thunderbird receives your email address domain. Your full email address is never processed or stored on our servers (unless you choose to share it when you send a crash report).

+

Technical data: Thunderbird also receives information about the application’s version and device operating system. When Thunderbird sends technical data to us, your IP address is temporarily collected as part of our server logs.

+

Set Up and Configure Your Calendar

+

Thunderbird collects the domain for your email/calendar, as well as technical data to set up and configure your calendar. Other information, like your name, your calendar events, and event attendees are stored locally on your computer and never sent to us.

+

You can connect your Google, Microsoft, or Apple calendar to Thunderbird and control your calendar right from Thunderbird.

+

We do not store your content from integrating Apple Calendar, Google Calendar, or Microsoft 365 with Thunderbird. That information stays on your computer. Nor do we share your content with any third party other than your calendar provider and anyone you specifically choose to send the appointments to.

+

Set Up and Schedule Calendar Appointments with Thunderbird Appointment

+

With Thunderbird Appointment, you can allow others to schedule appointments on your calendar.

+

You can connect your Google, Microsoft, or Apple calendar to Thunderbird Appointment to assist with scheduling.

+

If you choose to connect your Apple Calendar, Microsoft 365, or Google Calendar to Thunderbird Appointment, we will receive basic information about your calendar invites such as the title, date, stated location, the name and emails of the attendees, and any text in the appointment to display them within Thunderbird Appointment and allow you to invite others to schedule time in your calendar. We will receive technical and interaction data about your interactions with this feature such as how many events you create, whether you have connected to a Google, Microsoft, or Apple account.

+

We will only use your data to provide and improve the Thunderbird Appointment service.

+

Review Crash Reports

+

If Thunderbird crashes, we will ask you to share a report with more detailed information about the crash, but you always have the choice to decline. Thunderbird uses the information in the crash report to diagnose and correct the problem that caused the crash.

+

Sensitive data: Crash reports include a “dump file” of Thunderbird’s memory contents at the time of the crash, which may contain data that identifies you or is otherwise sensitive to you.

+

Webpage data: Crash reports include any active URLs at time of crash.

+

Add-on data: Crash reports include a list of all add-ons that you were using at the time of the crash, and the time since: the start-up of the program, the last crash, and the last install.

+

Technical data: Crash reports include data on why Thunderbird crashed and the state of device memory and execution during the crash. When Thunderbird sends technical data to us, your IP address is temporarily collected as part of our server logs.

+

Email address: If you choose, crash reports include your email address.

+

Read the full documentation here.

+

Improve Security for Our Users Everywhere

+

Technical data for updates: To ensure you have the most up-to-date version of the product, Thunderbird checks for updates by periodically connecting to Thunderbird’s servers. Your application version, language, and device operating system are used to apply the correct updates. Learn more.

+

Technical data for add-ons blocklist: To help to protect you from any malicious add-ons, Thunderbird periodically checks for blocklisted add-ons. Your Thunderbird version and language, device operating system, and list of installed add-ons are needed to apply and update the add-ons blocklist. Learn more.

+

Install and Update Add-Ons

+

You can install add-ons from addons.thunderbird.net or from the Thunderbird Add-ons Manager, which is accessible by clicking on Tools > Add-ons. To keep your installed add-ons up to date—like add-on descriptions, download counts, and ratings—the Thunderbird application periodically connects to our servers to install any updates.

+

Search queries: If you enter keywords into the search field for the Add-ons Manager, those keywords will be sent to Thunderbird to perform the search.

+

Interaction data: We receive aggregate data about visits to the Thunderbird website and the Add-ons Manager in Thunderbird, as well as interactions with content on those pages. Read about data practices on Mozilla websites.

+

Technical data for updates: Thunderbird periodically connects to our server to install updates to add-ons. Your installed add-ons, application version, language, and device operating system are used to apply the correct updates. When Thunderbird sends technical data to us, your IP address is temporarily collected as part of our server logs.

+

Thunderbird May Disclose Information To:

+

Mozilla Affiliates: Thunderbird is a project of MZLA Technologies Corporation, a subsidiary of Mozilla Foundation and as such, shares some of the same infrastructure. This means that, from time to time, your data (e.g., crash reports, and technical and interaction data) may be disclosed to Mozilla Corporation and Mozilla Foundation. If so, it will be maintained in accordance with the commitments we make in this Privacy Notice.

+

DNS servers, Standard Autoconfiguration URIs, and Mozilla's Configuration Database: To simplify the email set-up process, Thunderbird tries to determine the correct settings for your account by contacting Mozilla’s configuration database as well as external servers. These include DNS servers and standard autoconfiguration URIs. During this process, your email domain may be sent to Mozilla's configuration database, and your email address may be disclosed to your network administrators.

+

Amazon Web Services: Thunderbird uses Amazon Web Services (AWS) to host its servers and as a content delivery network. Your device’s IP address is collected as part of AWS’s server logs.

+

Email address providers: Thunderbird has partnered with Gandi.net and Mailfence to allow you to create a new email address through Thunderbird. If you choose to use this feature, your email address search terms are sent to Gandi.net and Mailfence to return available addresses. In addition, your country location is also shared to provide the correct prices. You can learn more about Gandi.net’s and Mailfence’s data practices by reading their privacy notices.

\ No newline at end of file diff --git a/frontend/src/assets/legal/en/terms.html b/frontend/src/assets/legal/en/terms.html new file mode 100644 index 000000000..09306a63f --- /dev/null +++ b/frontend/src/assets/legal/en/terms.html @@ -0,0 +1,65 @@ +

Websites & Communications Terms of Use

+

June 23, 2016

+

Terms of Use

+

1. Introduction

+

Please read the terms of this entire document  (“Terms”) carefully because it explains your rights and responsibilities when you visit any of Mozilla’s websites (“Websites”), or related feeds, social media, newsletters, source code repositories, and emails (together with Websites, these are collectively referred to as “Communications”). By accessing or signing up to receive Communications, you agree to be bound by these Terms.

+

Our Websites include multiple domains such as mozilla.org, mozillians.org, firefox.com, mozillafestival.org, openstandard.com, openbadges.org and webmaker.org. You may also recognize our Websites by nicknames such as Bugzilla@Mozilla, BMO, MozWiki, MoPad, MozReps, MDN, Marketplace, One and Done, SUMO, and AMO. +Some of our Websites connect you with links, apps or add-ons that are provided by other parties and are subject to separate Terms.

+

2. Account Registration

+

Some Websites require you to register for an account in order to access additional features of a Website or another Mozilla service. If applicable, additional terms will be presented to you. You are responsible for all activities under your account.

+

Some Websites allow you to create a username during registration. Your use of a username must comply with our Acceptable Use Policy.

+

3. Content Licensing

+

Our Communications include content such as articles, images, photographs, comments, software code, audio and video clips, and other materials (collectively, “Content”).  Content is authored by Mozilla, contributors to Mozilla projects, and other sources.

+

Content authored by Mozilla is generally made available for public sharing and reuse through open licenses such as Creative Commons (for expressive material) or the Mozilla Public License (for software code).  In most cases we ask Mozilla contributors to release Content under open licenses.

+

Some Content in our Communications is acquired from sources that prohibit further use of their Content without advance permission.  Where possible, the Content or Website footer will display a notice with the applicable license. You agree to abide by such notices.  Note the following specifics:

+ +

4. Content Submissions

+

You may contribute Content when interacting with our Communications, including but not limited to commenting on an article, blogging, contributing code, or contributing graphics or written material (each a “Submission”). Unless your Submission is made under a separate agreement with Mozilla, in which case that agreement will govern, then

+

For Submissions to Mozilla's open source projects:

+ +

For all other Submissions, you agree to the following in connection with each:

+ +

5. Privacy Policy & Cookies

+

The Mozilla Websites, Communications & Cookies Privacy Notice describes how we handle information that we receive from you in connection with our Communications. The Privacy Notice explains, for example, that we place certain cookies on our Websites and how you can opt-out.

+

6. Communications and Events

+

If you subscribe to receive our newsletters or register for an account in connection with any of our Websites, you may receive transactional emails from us in connection with your account (for example, legal, privacy, and security updates).

+

Some of our Websites have online tools that allow you to send emails to others. For example, you can invite your contacts to events on Mozillians.  You agree not to misuse others’ email addresses (for example, by spamming them).

+

Other Websites, like MozReps, provide tools that enable users to arrange physical events for anyone to attend. Please exercise caution and good judgment when attending events.

+

7. Notice of Claimed Infringement

+

For more information on how to report claims of copyright or trademark infringement, please see: https://www.mozilla.org/about/legal/report-infringement/.

+

8. Term; Termination

+

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 discontinuing your use of our Communications and, if applicable, deleting your account.

+

We may suspend or terminate your access to our Communications at any time for any reason, including, but not limited to, if we reasonably believe: (i) you have violated these Terms, our Acceptable Use Policy, or other relevant policy; (ii) you create risk or possible legal exposure for us; or (iii) our provision of the Communications to you is no longer commercially viable.

+

In all such cases, these Terms shall terminate, except that the following sections shall continue to apply: Indemnification, Disclaimer; Limitation of Liability, Miscellaneous.

+

9. Indemnification

+

You agree to defend, indemnify and hold harmless Mozilla, its contractors, contributors, licensors, and partners; and the respective directors, officers, employees and agents of the foregoing ("Indemnified Parties") from and against any and all third party claims and expenses, including attorneys' fees, arising out of or related to your use of our Communications (including, but not limited to, from your Submissions or from your violation of any these Terms).

+

10. Disclaimer; Limitation of Liability

+

THE COMMUNICATIONS 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 COMMUNICATIONS ARE FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, AND NON-INFRINGING. YOU BEAR THE ENTIRE RISK AS TO USING THE COMMUNICATIONS FOR YOUR PURPOSES AND AS TO THE QUALITY AND PERFORMANCE OF THE COMMUNICATIONS, INCLUDING WITHOUT LIMITATION THE RISK THAT YOUR HARDWARE, SOFTWARE, OR CONTENT IS DELETED OR CORRUPTED, THAT SOMEONE ELSE GAINS UNAUTHORIZED ACCESS TO YOUR INFORMATION, OR THAT ANOTHER USER MISUSES OR MISAPPROPRIATES YOUR SUBMISSION. 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.

+

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 COMMUNICATIONS, 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.

+

11. Modifications to these Terms

+

We may update these Terms from time to time to address a new feature of the Communications or to clarify a provision. The updated Terms will be posted online. If the changes are substantive, we will announce the update through our usual channels for such announcements such as blog posts, banners, emails, or forums. Your continued use of our Communications 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.

+

12. Miscellaneous

+

These Terms constitute the entire agreement between you and Mozilla concerning our Communications and supersede any prior versions of these Terms. The Communications and these Terms are governed by the laws of the state of California, U.S.A., excluding its conflict of law provisions. All claims and disputes arising out of the Communications or these Terms shall be brought exclusively in the courts of Santa Clara County, California, and you consent to personal jurisdiction in those courts. 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. In the event of a conflict between these Terms and relevant additional terms, the additional terms shall control.

+

13. Contact Us

+

Mozilla
+Attn: Mozilla – Legal Notices
+149 New Montgomery St.
+4th Floor
+San Francisco, CA 94105
+USA
+Telephone: 650-903-0800
+Fax: 650-903-0875
+Legal-notices at mozilla.com

\ No newline at end of file diff --git a/frontend/src/router.js b/frontend/src/router.js index f5e35fe5a..ae09b1a78 100644 --- a/frontend/src/router.js +++ b/frontend/src/router.js @@ -76,12 +76,12 @@ const routes = [ { path: '/privacy', name: 'privacy', - beforeEnter: () => { location.href = 'https://www.mozilla.org/en-US/privacy/websites/'; }, + component: () => import('@/views/LegalView'), }, { path: '/terms', name: 'terms', - beforeEnter: () => { location.href = 'https://www.mozilla.org/en-US/about/legal/terms/mozilla/'; }, + component: () => import('@/views/LegalView'), }, ]; diff --git a/frontend/src/views/LegalView.vue b/frontend/src/views/LegalView.vue new file mode 100644 index 000000000..f988cc3c8 --- /dev/null +++ b/frontend/src/views/LegalView.vue @@ -0,0 +1,49 @@ + + + +