Merge branch 'release-v0.6.5'

This commit is contained in:
Sam 2022-04-24 16:08:13 +02:00
commit 7778514eb8
96 changed files with 1808 additions and 602 deletions

View File

@ -1,5 +1,22 @@
# Change log
## Version 0.6.5 (2022/04/24)
It is now possible to start FitTrackee without a configured SMTP provider (see [documentation](https://samr1.github.io/FitTrackee/installation.html#emails)).
It reduces pre-requisites for single-user instances.
To manage users, a new [CLI](https://samr1.github.io/FitTrackee/cli.html) is available.
### Issues Closed
#### Features
* [#180](https://github.com/SamR1/FitTrackee/issues/180) - allow using FitTrackee without SMTP server
In this release 1 issue was closed.
## Version 0.6.4 (2022/04/23)
### Issues Closed

View File

@ -1,4 +1,4 @@
FROM python:3.9
FROM python:3.10
# set working directory
RUN mkdir -p /usr/src/app

View File

@ -89,11 +89,11 @@ html:
install-db:
psql -U postgres -f db/create.sql
$(FLASK) db upgrade --directory $(MIGRATIONS)
$(FTCLI) db upgrade
init-db:
$(FLASK) drop-db
$(FLASK) db upgrade --directory $(MIGRATIONS)
$(FTCLI) db drop
$(FTCLI) db upgrade
install: install-client install-python
@ -164,7 +164,8 @@ serve-python-dev:
$(FLASK) run --with-threads -h $(HOST) -p $(PORT) --cert=adhoc
set-admin:
$(FLASK) users set-admin $(USERNAME)
echo "Deprecated command, will be removed in a next version. Use 'user-set-admin' instead."
$(FTCLI) users update $(USERNAME) --set-admin true
test-e2e:
$(PYTEST) e2e --driver firefox $(PYTEST_ARGS)
@ -185,4 +186,17 @@ type-check:
$(MYPY) fittrackee
upgrade-db:
$(FLASK) db upgrade --directory $(MIGRATIONS)
$(FTCLI) db upgrade
user-activate:
$(FTCLI) users update $(USERNAME) --activate
user-reset-password:
$(FTCLI) users update $(USERNAME) --reset-password
ADMIN := true
user-set-admin:
$(FTCLI) users update $(USERNAME) --set-admin $(ADMIN)
user-update-email:
$(FTCLI) users update $(USERNAME) --update-email $(EMAIL)

View File

@ -26,6 +26,7 @@ PYTEST = $(VENV)/bin/py.test -c pyproject.toml -W ignore::DeprecationWarning
GUNICORN = $(VENV)/bin/gunicorn
BLACK = $(VENV)/bin/black
MYPY = $(VENV)/bin/mypy
FTCLI = $(VENV)/bin/ftcli
# Node env
NODE_MODULES = $(PWD)/fittrackee_client/node_modules

View File

@ -1 +1 @@
0.6.4
0.6.5

View File

@ -4,5 +4,5 @@ cd /usr/src/app
source .env.docker
flask drop-db
flask db upgrade --directory fittrackee/migrations
ftcli db drop
ftcli db upgrade

View File

@ -4,4 +4,4 @@ cd /usr/src/app
source .env.docker
flask users set-admin $1
ftcli users update $1 --set-admin true

View File

@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 5c4236cdf8857210c21f0a7da25523a7
config: 1ea083693023f346a774e8d4c5d799a3
tags: 645f666f9bcd5a90fca523b33c5a78b7

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 KiB

After

Width:  |  Height:  |  Size: 539 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 KiB

After

Width:  |  Height:  |  Size: 369 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 103 KiB

View File

@ -1,5 +1,22 @@
# Change log
## Version 0.6.5 (2022/04/24)
It is now possible to start FitTrackee without a configured SMTP provider (see [documentation](https://samr1.github.io/FitTrackee/installation.html#emails)).
It reduces pre-requisites for single-user instances.
To manage users, a new [CLI](https://samr1.github.io/FitTrackee/cli.html) is available.
### Issues Closed
#### Features
* [#180](https://github.com/SamR1/FitTrackee/issues/180) - allow using FitTrackee without SMTP server
In this release 1 issue was closed.
## Version 0.6.4 (2022/04/23)
### Issues Closed

67
docs/_sources/cli.rst.txt Normal file
View File

@ -0,0 +1,67 @@
Command line interface
######################
A command line interface (CLI) is available to manage database and users.
.. code-block:: bash
$ ftcli
Usage: ftcli [OPTIONS] COMMAND [ARGS]...
FitTrackee Command Line Interface
Options:
--help Show this message and exit.
Commands:
db Manage database.
users Manage users.
.. warning::
| The following commands are now deprecated and will be removed in a next version:
| - ``fittrackee_set_admin``
| - ``fittrackee_upgrade_db``
Database
~~~~~~~~
``ftcli db upgrade``
""""""""""""""""""""
.. versionadded:: 0.6.5
Apply migrations.
``ftcli db drop``
"""""""""""""""""
.. versionadded:: 0.6.5
Empty database and delete uploaded files, only on development environments.
Users
~~~~~
``ftcli users update``
""""""""""""""""""""""
.. versionadded:: 0.6.5
Modify a user account (admin rights, active status, email and password).
.. cssclass:: table-bordered
.. list-table::
:widths: 25 50
:header-rows: 1
* - Options
- Description
* - ``--set-admin BOOLEAN``
- Add/remove admin rights (when adding admin rights, it also activates user account if not active).
* - ``--activate``
- Activate user account.
* - ``--reset-password``
- Reset user password (a new password will be displayed).
* - ``--update-email EMAIL``
- Update user email.

View File

@ -60,10 +60,11 @@ Workouts
Account & preferences
^^^^^^^^^^^^^^^^^^^^^
- A user can create, update and deleted his account.
- After registration, the user account is inactive and an email with confirmation instructions is sent to activate it. A user with an inactive account cannot log in. (*new in 0.6.0*)
- After registration, the user account is inactive and an email with confirmation instructions is sent to activate it.
A user with an inactive account cannot log in. (*new in 0.6.0*)
.. note::
The command line to add admin rights activates the account if it is inactive.
In case email sending is not configured, a `command line <cli.html#ftcli-users-update>`__ allows to activate users account.
- A user can set language, timezone and first day of week.
- A user can reset his password (*new in 0.3.0*)
@ -97,6 +98,9 @@ Administration
.. warning::
Updating server configuration may be necessary to handle large files (like `nginx <https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size>`_ for instance).
.. note::
If email sending is disabled, a warning is displayed.
- **Users**
@ -105,7 +109,7 @@ Administration
- add/remove administration rights
- activate his account (*new in 0.6.0*)
- update his email (in case his account is locked) (*new in 0.6.0*)
- reset his password (in case his account is locked) (*new in 0.6.0*)
- reset his password (in case his account is locked) (*new in 0.6.0*). If email sending is disabled, it is only possible via CLI.
- delete a user
- **Sports**

View File

@ -34,6 +34,7 @@ Table of contents
features
installation
cli
api/index
troubleshooting/index
changelog

View File

@ -22,9 +22,8 @@ Prerequisites
- Python 3.7+
- PostgreSQL database (10+)
- SMTP provider
- Redis for task queue (to send emails)
- API key from `Dark Sky <https://darksky.net/dev>`__ [not mandatory]
- SMTP provider and Redis for task queue (if email sending is enabled)
- API key from `Dark Sky <https://darksky.net/dev>`__ (not mandatory)
- `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
- `Yarn <https://yarnpkg.com>`__ (for development only)
- Docker and Docker Compose (for development or evaluation purposes)
@ -133,6 +132,13 @@ deployment method.
Email URL with credentials, see `Emails <installation.html#emails>`__.
.. versionchanged:: 0.6.5
:default: empty string
.. danger::
If the email URL is empty, email sending will be disabled.
.. warning::
If the email URL is invalid, the application may not start.
@ -214,7 +220,7 @@ To send emails, a valid ``EMAIL_URL`` must be provided:
| - If the email URL is invalid, the application may not start.
| - Sending emails with Office365 may not work if SMTP auth is disabled.
.. versionadded:: 0.5.3
.. versionchanged:: 0.5.3
| Credentials can be omitted: ``smtp://smtp.example.com:25``.
| If ``:<port>`` is omitted, the port defaults to 25.
@ -229,6 +235,11 @@ Emails sent by FitTrackee are:
- email change (to old and new email adresses)
- password change
.. versionchanged:: 0.6.5
| For single-user instance, it is possible to disable email sending with an empty ``EMAIL_URL`` (in this case, no need to start dramatiq workers).
| A `CLI <cli.html#ftcli-users-update>`__ is available to activate account and modify email and password.
Map tile server
^^^^^^^^^^^^^^^
@ -288,7 +299,7 @@ For instance, copy and update ``.env`` file from ``.env.example`` and source the
.. code-block:: bash
$ fittrackee_upgrade_db
$ ftcli db upgrade
- Start the application
@ -296,7 +307,7 @@ For instance, copy and update ``.env`` file from ``.env.example`` and source the
$ fittrackee
- Start task queue workers
- Start task queue workers if email sending is enabled.
.. code-block:: bash
@ -311,7 +322,7 @@ For instance, copy and update ``.env`` file from ``.env.example`` and source the
.. code:: bash
$ fittrackee_set_admin <username>
$ ftcli users update <username> --set-admin true
.. note::
If the user account is inactive, it activates it.
@ -373,7 +384,7 @@ Dev environment
.. code:: bash
$ make set-admin USERNAME=<username>
$ make user-set-admin USERNAME=<username>
.. note::
If the user account is inactive, it activates it.
@ -384,13 +395,13 @@ Production environment
.. warning::
| Note that FitTrackee is under heavy development, some features may be unstable.
- Download the last release (for now, it is the release v0.6.4):
- Download the last release (for now, it is the release v0.6.5):
.. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.4.tar.gz
$ tar -xzf v0.6.4.tar.gz
$ mv FitTrackee-0.6.4 FitTrackee
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.5.tar.gz
$ tar -xzf v0.6.5.tar.gz
$ mv FitTrackee-0.6.5 FitTrackee
$ cd FitTrackee
- Create **.env** from example and update it
@ -415,13 +426,16 @@ Production environment
$ make run
.. note::
If email sending is disabled: ``$ make run-server``
- Open http://localhost:5000 and register
- To set admin rights to the newly created account, use the following command line:
.. code:: bash
$ make set-admin USERNAME=<username>
$ make user-set-admin USERNAME=<username>
.. note::
If the user account is inactive, it activates it.
@ -457,9 +471,9 @@ From PyPI
.. code-block:: bash
$ fittrackee_upgrade_db
$ ftcli db upgrade
- Restart the application and task queue workers.
- Restart the application and task queue workers (if email sending is enabled).
From sources
@ -507,13 +521,13 @@ Prod environment
- Change to the directory where FitTrackee directory is located
- Download the last release (for now, it is the release v0.6.4) and overwrite existing files:
- Download the last release (for now, it is the release v0.6.5) and overwrite existing files:
.. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.4.tar.gz
$ tar -xzf v0.6.4.tar.gz
$ cp -R FitTrackee-0.6.4/* FitTrackee/
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.5.tar.gz
$ tar -xzf v0.6.5.tar.gz
$ cp -R FitTrackee-0.6.5/* FitTrackee/
$ cd FitTrackee
- Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__).
@ -536,6 +550,8 @@ Prod environment
$ make run
.. note::
If email sending is disabled: ``$ make run-server``
Deployment
~~~~~~~~~~

View File

@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '0.6.4',
VERSION: '0.6.5',
LANGUAGE: 'None',
COLLAPSE_INDEX: false,
BUILDER: 'html',

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Authentication &#8212; FitTrackee 0.6.4
<title>Authentication &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>
@ -237,6 +238,7 @@ character “_” allowed</p></li>
<dt class="sig sig-object http" id="post--api-auth-account-resend-confirmation">
<span class="sig-name descname"><span class="pre">POST</span> </span><span class="sig-name descname"><span class="pre">/api/auth/account/resend-confirmation</span></span><a class="headerlink" href="#post--api-auth-account-resend-confirmation" title="Permalink to this definition"></a></dt>
<dd><p>resend email with instructions to confirm account</p>
<p>If email sending is disabled, this endpoint is not available</p>
<p><strong>Example request</strong>:</p>
<div class="highlight-http notranslate"><div class="highlight"><pre><span></span><span class="nf">POST</span> <span class="nn">/api/auth/account/resend-confirmation</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Content-Type</span><span class="o">:</span> <span class="l">application/json</span>
@ -262,6 +264,7 @@ character “_” allowed</p></li>
<dd class="field-even"><ul class="simple">
<li><p><span><a class="reference external" href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1">200 OK</a></span> confirmation email resent</p></li>
<li><p><span><a class="reference external" href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1">400 Bad Request</a></span> invalid payload</p></li>
<li><p><span><a class="reference external" href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5">404 Not Found</a></span> the requested URL was not found on the server</p></li>
<li><p><span><a class="reference external" href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1">500 Internal Server Error</a></span> error, please try again or contact the administrator</p></li>
</ul>
</dd>
@ -857,6 +860,7 @@ character “_” allowed</p></li>
<dt class="sig sig-object http" id="post--api-auth-password-reset-request">
<span class="sig-name descname"><span class="pre">POST</span> </span><span class="sig-name descname"><span class="pre">/api/auth/password/reset-request</span></span><a class="headerlink" href="#post--api-auth-password-reset-request" title="Permalink to this definition"></a></dt>
<dd><p>handle password reset request</p>
<p>If email sending is disabled, this endpoint is not available</p>
<p><strong>Example request</strong>:</p>
<div class="highlight-http notranslate"><div class="highlight"><pre><span></span><span class="nf">POST</span> <span class="nn">/api/auth/password/reset-request</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Content-Type</span><span class="o">:</span> <span class="l">application/json</span>
@ -882,6 +886,7 @@ character “_” allowed</p></li>
<dd class="field-even"><ul class="simple">
<li><p><span><a class="reference external" href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1">200 OK</a></span> password reset request processed</p></li>
<li><p><span><a class="reference external" href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1">400 Bad Request</a></span> invalid payload</p></li>
<li><p><span><a class="reference external" href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5">404 Not Found</a></span> the requested URL was not found on the server</p></li>
</ul>
</dd>
</dl>
@ -891,7 +896,7 @@ character “_” allowed</p></li>
<dt class="sig sig-object http" id="patch--api-auth-profile-edit-account">
<span class="sig-name descname"><span class="pre">PATCH</span> </span><span class="sig-name descname"><span class="pre">/api/auth/profile/edit/account</span></span><a class="headerlink" href="#patch--api-auth-profile-edit-account" title="Permalink to this definition"></a></dt>
<dd><p>update authenticated user email and password</p>
<p>It sends emails:</p>
<p>It sends emails if sending is enabled:</p>
<ul class="simple">
<li><p>Password change</p></li>
<li><p>Email change:</p>
@ -1021,6 +1026,7 @@ character “_” allowed</p></li>
<dt class="sig sig-object http" id="post--api-auth-password-update">
<span class="sig-name descname"><span class="pre">POST</span> </span><span class="sig-name descname"><span class="pre">/api/auth/password/update</span></span><a class="headerlink" href="#post--api-auth-password-update" title="Permalink to this definition"></a></dt>
<dd><p>update user password after password reset request</p>
<p>It sends emails if sending is enabled</p>
<p><strong>Example request</strong>:</p>
<div class="highlight-http notranslate"><div class="highlight"><pre><span></span><span class="nf">POST</span> <span class="nn">/api/auth/password/update</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Content-Type</span><span class="o">:</span> <span class="l">application/json</span>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Configuration &#8212; FitTrackee 0.6.4
<title>Configuration &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>
@ -144,12 +145,13 @@
<span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;admin_contact&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;admin@example.com&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;gpx_limit_import&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;is_email_sending_enabled&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;is_registration_enabled&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;max_single_file_size&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">1048576</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;max_users&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;max_zip_file_size&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10485760</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;map_attribution&quot;</span><span class="p">:</span><span class="w"> </span><span class="nt">&quot;&amp;copy; &lt;a href=http://www.openstreetmap.org/copyright&gt;OpenStreetMap&lt;/a&gt; contributors&quot;</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.6.4&quot;</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.6.5&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;success&quot;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
@ -183,12 +185,13 @@
<span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;admin_contact&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;admin@example.com&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;gpx_limit_import&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;is_email_sending_enabled&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;is_registration_enabled&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;max_single_file_size&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">1048576</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;max_users&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;max_zip_file_size&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10485760</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;map_attribution&quot;</span><span class="p">:</span><span class="w"> </span><span class="nt">&quot;&amp;copy; &lt;a href=http://www.openstreetmap.org/copyright&gt;OpenStreetMap&lt;/a&gt; contributors&quot;</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.6.4&quot;</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.6.5&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;success&quot;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>API documentation &#8212; FitTrackee 0.6.4
<title>API documentation &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -17,7 +17,7 @@
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Authentication" href="auth.html" />
<link rel="prev" title="Installation" href="../installation.html" />
<link rel="prev" title="Command line interface" href="../cli.html" />
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>
@ -87,7 +88,7 @@
<li>
<a href="../installation.html" title="Previous Chapter: Installation"><span class="glyphicon glyphicon-chevron-left visible-sm"></span><span class="hidden-sm hidden-tablet">&laquo; Installation</span>
<a href="../cli.html" title="Previous Chapter: Command line interface"><span class="glyphicon glyphicon-chevron-left visible-sm"></span><span class="hidden-sm hidden-tablet">&laquo; Command line ...</span>
</a>
</li>
<li>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Records &#8212; FitTrackee 0.6.4
<title>Records &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Sports &#8212; FitTrackee 0.6.4
<title>Sports &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Statistics &#8212; FitTrackee 0.6.4
<title>Statistics &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Users &#8212; FitTrackee 0.6.4
<title>Users &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>
@ -429,8 +430,9 @@ details.</p>
<dd><p>Update user account</p>
<ul class="simple">
<li><p>add/remove admin rights (regardless user account status)</p></li>
<li><p>reset password (and send email to update user password)</p></li>
<li><p>update user email (and send email to update user password)</p></li>
<li><p>reset password (and send email to update user password,
if sending enabled)</p></li>
<li><p>update user email (and send email to new user email, if sending enabled)</p></li>
<li><p>activate account for an inactive user</p></li>
</ul>
<p>Only user with admin rights can modify another user</p>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Workouts &#8212; FitTrackee 0.6.4
<title>Workouts &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Change log &#8212; FitTrackee 0.6.4
<title>Change log &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -39,7 +39,7 @@
</button>
<a class="navbar-brand" href="index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -60,6 +60,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="api/index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Change log</a></li>
@ -77,8 +78,15 @@
role="menu"
aria-labelledby="dLabelLocalToc"><ul>
<li><a class="reference internal" href="#">Change log</a><ul>
<li><a class="reference internal" href="#version-0-6-4-2022-04-23">Version 0.6.4 (2022/04/23)</a><ul>
<li><a class="reference internal" href="#version-0-6-5-2022-04-24">Version 0.6.5 (2022/04/24)</a><ul>
<li><a class="reference internal" href="#issues-closed">Issues Closed</a><ul>
<li><a class="reference internal" href="#features">Features</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-6-4-2022-04-23">Version 0.6.4 (2022/04/23)</a><ul>
<li><a class="reference internal" href="#id1">Issues Closed</a><ul>
<li><a class="reference internal" href="#bugs-fixed">Bugs Fixed</a></li>
</ul>
</li>
@ -86,235 +94,235 @@
</li>
<li><a class="reference internal" href="#version-0-6-3-2022-04-09">Version 0.6.3 (2022/04/09)</a><ul>
<li><a class="reference internal" href="#pull-requests">Pull Requests</a><ul>
<li><a class="reference internal" href="#id1">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id2">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-6-2-2022-04-03">Version 0.6.2 (2022/04/03)</a><ul>
<li><a class="reference internal" href="#id2">Issues Closed</a><ul>
<li><a class="reference internal" href="#id3">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id3">Issues Closed</a><ul>
<li><a class="reference internal" href="#id4">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-6-1-2022-03-27">Version 0.6.1 (2022/03/27)</a><ul>
<li><a class="reference internal" href="#id4">Issues Closed</a><ul>
<li><a class="reference internal" href="#id5">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id5">Issues Closed</a><ul>
<li><a class="reference internal" href="#id6">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-6-0-2022-03-27">Version 0.6.0 (2022/03/27)</a><ul>
<li><a class="reference internal" href="#id6">Issues Closed</a><ul>
<li><a class="reference internal" href="#features">Features</a></li>
<li><a class="reference internal" href="#id7">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id7">Issues Closed</a><ul>
<li><a class="reference internal" href="#id8">Features</a></li>
<li><a class="reference internal" href="#id9">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id8">Pull Requests</a><ul>
<li><a class="reference internal" href="#id9">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id10">Pull Requests</a><ul>
<li><a class="reference internal" href="#id11">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-5-7-2022-02-13">Version 0.5.7 (2022/02/13)</a><ul>
<li><a class="reference internal" href="#id10">Issues Closed</a><ul>
<li><a class="reference internal" href="#id12">Issues Closed</a><ul>
<li><a class="reference internal" href="#misc">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id11">Pull Requests</a><ul>
<li><a class="reference internal" href="#id13">Pull Requests</a><ul>
<li><a class="reference internal" href="#security">Security</a></li>
<li><a class="reference internal" href="#id12">Misc</a></li>
<li><a class="reference internal" href="#id14">Misc</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-5-6-2022-02-05">Version 0.5.6 (2022/02/05)</a><ul>
<li><a class="reference internal" href="#id13">Issues Closed</a><ul>
<li><a class="reference internal" href="#id14">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id15">Issues Closed</a><ul>
<li><a class="reference internal" href="#id16">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id15">Pull Requests</a></li>
<li><a class="reference internal" href="#id17">Pull Requests</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-5-5-2022-01-19">Version 0.5.5 (2022/01/19)</a><ul>
<li><a class="reference internal" href="#id16">Issues Closed</a><ul>
<li><a class="reference internal" href="#new-features">New Features</a></li>
<li><a class="reference internal" href="#id17">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-5-4-2022-01-01">Version 0.5.4 (2022/01/01)</a><ul>
<li><a class="reference internal" href="#id18">Issues Closed</a><ul>
<li><a class="reference internal" href="#new-features">New Features</a></li>
<li><a class="reference internal" href="#id19">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-5-3-2022-01-01">Version 0.5.3 (2022/01/01)</a><ul>
<li><a class="reference internal" href="#version-0-5-4-2022-01-01">Version 0.5.4 (2022/01/01)</a><ul>
<li><a class="reference internal" href="#id20">Issues Closed</a><ul>
<li><a class="reference internal" href="#id21">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-5-2-2021-12-19">Version 0.5.2 (2021/12/19)</a><ul>
<li><a class="reference internal" href="#version-0-5-3-2022-01-01">Version 0.5.3 (2022/01/01)</a><ul>
<li><a class="reference internal" href="#id22">Issues Closed</a><ul>
<li><a class="reference internal" href="#id23">New Features</a></li>
<li><a class="reference internal" href="#id23">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-5-1-2021-11-30">Version 0.5.1 (2021/11/30)</a><ul>
<li><a class="reference internal" href="#version-0-5-2-2021-12-19">Version 0.5.2 (2021/12/19)</a><ul>
<li><a class="reference internal" href="#id24">Issues Closed</a><ul>
<li><a class="reference internal" href="#id25">New Features</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-5-0-2021-11-14">Version 0.5.0 (2021/11/14)</a><ul>
<li><a class="reference internal" href="#version-0-5-1-2021-11-30">Version 0.5.1 (2021/11/30)</a><ul>
<li><a class="reference internal" href="#id26">Issues Closed</a><ul>
<li><a class="reference internal" href="#id27">New Features</a></li>
<li><a class="reference internal" href="#id28">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id29">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id30">Pull Requests</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-5-0-2021-11-14">Version 0.5.0 (2021/11/14)</a><ul>
<li><a class="reference internal" href="#id28">Issues Closed</a><ul>
<li><a class="reference internal" href="#id29">New Features</a></li>
<li><a class="reference internal" href="#id30">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id31">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id32">Pull Requests</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-9-2021-07-16">Version 0.4.9 (2021/07/16)</a><ul>
<li><a class="reference internal" href="#id31">Issues Closed</a><ul>
<li><a class="reference internal" href="#id32">New Features</a></li>
<li><a class="reference internal" href="#id33">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-8-2021-07-03">Version 0.4.8 (2021/07/03)</a><ul>
<li><a class="reference internal" href="#id34">Issues Closed</a><ul>
<li><a class="reference internal" href="#id33">Issues Closed</a><ul>
<li><a class="reference internal" href="#id34">New Features</a></li>
<li><a class="reference internal" href="#id35">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-7-2021-04-07">Version 0.4.7 (2021/04/07)</a><ul>
<li><a class="reference internal" href="#version-0-4-8-2021-07-03">Version 0.4.8 (2021/07/03)</a><ul>
<li><a class="reference internal" href="#id36">Issues Closed</a><ul>
<li><a class="reference internal" href="#id37">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id38">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-7-2021-04-07">Version 0.4.7 (2021/04/07)</a><ul>
<li><a class="reference internal" href="#id38">Issues Closed</a><ul>
<li><a class="reference internal" href="#id39">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id40">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-6-2021-02-21">Version 0.4.6 (2021/02/21)</a><ul>
<li><a class="reference internal" href="#id39">Issues Closed</a><ul>
<li><a class="reference internal" href="#id40">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-5-2021-02-17">Version 0.4.5 (2021/02/17)</a><ul>
<li><a class="reference internal" href="#id41">Issues Closed</a><ul>
<li><a class="reference internal" href="#id42">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-4-2021-01-31">Version 0.4.4 (2021/01/31)</a><ul>
<li><a class="reference internal" href="#version-0-4-5-2021-02-17">Version 0.4.5 (2021/02/17)</a><ul>
<li><a class="reference internal" href="#id43">Issues Closed</a><ul>
<li><a class="reference internal" href="#id44">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id45">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-4-2021-01-31">Version 0.4.4 (2021/01/31)</a><ul>
<li><a class="reference internal" href="#id45">Issues Closed</a><ul>
<li><a class="reference internal" href="#id46">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id47">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-3-2021-01-10">Version 0.4.3 (2021/01/10)</a><ul>
<li><a class="reference internal" href="#id46">Issues Closed</a><ul>
<li><a class="reference internal" href="#id47">New Features</a></li>
<li><a class="reference internal" href="#id48">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id48">Issues Closed</a><ul>
<li><a class="reference internal" href="#id49">New Features</a></li>
<li><a class="reference internal" href="#id50">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-2-2021-01-03">Version 0.4.2 (2021/01/03)</a><ul>
<li><a class="reference internal" href="#id49">Misc</a></li>
<li><a class="reference internal" href="#id51">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-1-2020-12-31">Version 0.4.1 (2020/12/31)</a><ul>
<li><a class="reference internal" href="#id50">Issues Closed</a><ul>
<li><a class="reference internal" href="#id51">New Features</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-0-fittrackee-on-pypi-2020-09-19">Version 0.4.0 - FitTrackee on PyPI (2020/09/19)</a><ul>
<li><a class="reference internal" href="#id52">Issues Closed</a><ul>
<li><a class="reference internal" href="#id53">New Features</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-3-0-administration-2020-07-15">Version 0.3.0 - Administration (2020/07/15)</a><ul>
<li><a class="reference internal" href="#version-0-4-0-fittrackee-on-pypi-2020-09-19">Version 0.4.0 - FitTrackee on PyPI (2020/09/19)</a><ul>
<li><a class="reference internal" href="#id54">Issues Closed</a><ul>
<li><a class="reference internal" href="#id55">New Features</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-3-0-administration-2020-07-15">Version 0.3.0 - Administration (2020/07/15)</a><ul>
<li><a class="reference internal" href="#id56">Issues Closed</a><ul>
<li><a class="reference internal" href="#id57">New Features</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-2-5-fix-and-improvements-2020-01-31">Version 0.2.5 - Fix and improvements (2020/01/31)</a><ul>
<li><a class="reference internal" href="#id56">Misc</a></li>
<li><a class="reference internal" href="#id58">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-2-4-minor-fix-2020-01-30">Version 0.2.4 - Minor fix (2020/01/30)</a><ul>
<li><a class="reference internal" href="#id57">Issues Closed</a><ul>
<li><a class="reference internal" href="#id58">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id59">Issues Closed</a><ul>
<li><a class="reference internal" href="#id60">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-2-3-fittrackee-available-in-french-2019-12-29">Version 0.2.3 - FitTrackee available in French (2019/12/29)</a><ul>
<li><a class="reference internal" href="#id59">Issues Closed</a><ul>
<li><a class="reference internal" href="#id60">New Features</a></li>
<li><a class="reference internal" href="#id61">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-2-2-statistics-fix-2019-09-23">Version 0.2.2 - Statistics fix (2019/09/23)</a><ul>
<li><a class="reference internal" href="#id62">Issues Closed</a><ul>
<li><a class="reference internal" href="#id61">Issues Closed</a><ul>
<li><a class="reference internal" href="#id62">New Features</a></li>
<li><a class="reference internal" href="#id63">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-2-1-fix-and-improvements-2019-09-01">Version 0.2.1 - Fix and improvements (2019/09/01)</a><ul>
<li><a class="reference internal" href="#version-0-2-2-statistics-fix-2019-09-23">Version 0.2.2 - Statistics fix (2019/09/23)</a><ul>
<li><a class="reference internal" href="#id64">Issues Closed</a><ul>
<li><a class="reference internal" href="#id65">New Features</a></li>
<li><a class="reference internal" href="#id66">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id65">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id67">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-2-1-fix-and-improvements-2019-09-01">Version 0.2.1 - Fix and improvements (2019/09/01)</a><ul>
<li><a class="reference internal" href="#id66">Issues Closed</a><ul>
<li><a class="reference internal" href="#id67">New Features</a></li>
<li><a class="reference internal" href="#id68">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id69">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-2-0-statistics-2019-07-07">Version 0.2.0 - Statistics (2019/07/07)</a><ul>
<li><a class="reference internal" href="#id68">Issues Closed</a><ul>
<li><a class="reference internal" href="#id69">New Features</a></li>
<li><a class="reference internal" href="#id70">Issues Closed</a><ul>
<li><a class="reference internal" href="#id71">New Features</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id70">Misc</a></li>
<li><a class="reference internal" href="#id72">Misc</a></li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-1-1-fix-and-improvements-2019-02-07">Version 0.1.1 - Fix and improvements (2019/02/07)</a><ul>
<li><a class="reference internal" href="#id71">Issues Closed</a><ul>
<li><a class="reference internal" href="#id72">New Features</a></li>
<li><a class="reference internal" href="#id73">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id73">Issues Closed</a><ul>
<li><a class="reference internal" href="#id74">New Features</a></li>
<li><a class="reference internal" href="#id75">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-1-0-first-release-2018-07-04">Version 0.1.0 - First release 🎉 (2018-07-04)</a><ul>
<li><a class="reference internal" href="#id74">Issues Closed</a><ul>
<li><a class="reference internal" href="#id75">New Features</a></li>
<li><a class="reference internal" href="#id76">Issues Closed</a><ul>
<li><a class="reference internal" href="#id77">New Features</a></li>
</ul>
</li>
</ul>
@ -366,10 +374,26 @@
<section id="change-log">
<h1>Change log<a class="headerlink" href="#change-log" title="Permalink to this headline"></a></h1>
<section id="version-0-6-4-2022-04-23">
<h2>Version 0.6.4 (2022/04/23)<a class="headerlink" href="#version-0-6-4-2022-04-23" title="Permalink to this headline"></a></h2>
<section id="version-0-6-5-2022-04-24">
<h2>Version 0.6.5 (2022/04/24)<a class="headerlink" href="#version-0-6-5-2022-04-24" title="Permalink to this headline"></a></h2>
<p>It is now possible to start FitTrackee without a configured SMTP provider (see <a class="reference external" href="https://samr1.github.io/FitTrackee/installation.html#emails">documentation</a>).
It reduces pre-requisites for single-user instances.</p>
<p>To manage users, a new <a class="reference external" href="https://samr1.github.io/FitTrackee/cli.html">CLI</a> is available.</p>
<section id="issues-closed">
<h3>Issues Closed<a class="headerlink" href="#issues-closed" title="Permalink to this headline"></a></h3>
<section id="features">
<h4>Features<a class="headerlink" href="#features" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/180">#180</a> - allow using FitTrackee without SMTP server</p></li>
</ul>
<p>In this release 1 issue was closed.</p>
</section>
</section>
</section>
<section id="version-0-6-4-2022-04-23">
<h2>Version 0.6.4 (2022/04/23)<a class="headerlink" href="#version-0-6-4-2022-04-23" title="Permalink to this headline"></a></h2>
<section id="id1">
<h3>Issues Closed<a class="headerlink" href="#id1" title="Permalink to this headline"></a></h3>
<section id="bugs-fixed">
<h4>Bugs Fixed<a class="headerlink" href="#bugs-fixed" title="Permalink to this headline"></a></h4>
<ul class="simple">
@ -383,8 +407,8 @@
<h2>Version 0.6.3 (2022/04/09)<a class="headerlink" href="#version-0-6-3-2022-04-09" title="Permalink to this headline"></a></h2>
<section id="pull-requests">
<h3>Pull Requests<a class="headerlink" href="#pull-requests" title="Permalink to this headline"></a></h3>
<section id="id1">
<h4>Bugs Fixed<a class="headerlink" href="#id1" title="Permalink to this headline"></a></h4>
<section id="id2">
<h4>Bugs Fixed<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/pull/177">#177</a> - Minor fixes</p>
<ul>
@ -398,10 +422,10 @@
</section>
<section id="version-0-6-2-2022-04-03">
<h2>Version 0.6.2 (2022/04/03)<a class="headerlink" href="#version-0-6-2-2022-04-03" title="Permalink to this headline"></a></h2>
<section id="id2">
<h3>Issues Closed<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h3>
<section id="id3">
<h4>Bugs Fixed<a class="headerlink" href="#id3" title="Permalink to this headline"></a></h4>
<h3>Issues Closed<a class="headerlink" href="#id3" title="Permalink to this headline"></a></h3>
<section id="id4">
<h4>Bugs Fixed<a class="headerlink" href="#id4" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/175">#175</a> - Distance card on dashboard is not refreshed</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/173">#173</a> - link to user profile in workout card is incorrect</p></li>
@ -412,10 +436,10 @@
</section>
<section id="version-0-6-1-2022-03-27">
<h2>Version 0.6.1 (2022/03/27)<a class="headerlink" href="#version-0-6-1-2022-03-27" title="Permalink to this headline"></a></h2>
<section id="id4">
<h3>Issues Closed<a class="headerlink" href="#id4" title="Permalink to this headline"></a></h3>
<section id="id5">
<h4>Bugs Fixed<a class="headerlink" href="#id5" title="Permalink to this headline"></a></h4>
<h3>Issues Closed<a class="headerlink" href="#id5" title="Permalink to this headline"></a></h3>
<section id="id6">
<h4>Bugs Fixed<a class="headerlink" href="#id6" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/171">#171</a> - Stats chart is not updated correctly</p></li>
</ul>
@ -426,26 +450,26 @@
<section id="version-0-6-0-2022-03-27">
<h2>Version 0.6.0 (2022/03/27)<a class="headerlink" href="#version-0-6-0-2022-03-27" title="Permalink to this headline"></a></h2>
<p>This version introduces some changes on <a class="reference external" href="https://samr1.github.io/FitTrackee/features.html#account-preferences">user registration</a>.<br />From now on, a user needs to confirm his account after registration (an email with confirmation instructions is sent after registration).</p>
<section id="id6">
<h3>Issues Closed<a class="headerlink" href="#id6" title="Permalink to this headline"></a></h3>
<section id="features">
<h4>Features<a class="headerlink" href="#features" title="Permalink to this headline"></a></h4>
<section id="id7">
<h3>Issues Closed<a class="headerlink" href="#id7" title="Permalink to this headline"></a></h3>
<section id="id8">
<h4>Features<a class="headerlink" href="#id8" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/155">#155</a> - Improve user registration</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/106">#106</a> - Allow user to update email</p></li>
</ul>
</section>
<section id="id7">
<h4>Bugs Fixed<a class="headerlink" href="#id7" title="Permalink to this headline"></a></h4>
<section id="id9">
<h4>Bugs Fixed<a class="headerlink" href="#id9" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/169">#169</a> - user picture is not refreshed after update</p></li>
</ul>
</section>
</section>
<section id="id8">
<h3>Pull Requests<a class="headerlink" href="#id8" title="Permalink to this headline"></a></h3>
<section id="id9">
<h4>Bugs Fixed<a class="headerlink" href="#id9" title="Permalink to this headline"></a></h4>
<section id="id10">
<h3>Pull Requests<a class="headerlink" href="#id10" title="Permalink to this headline"></a></h3>
<section id="id11">
<h4>Bugs Fixed<a class="headerlink" href="#id11" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/pull/161">#161</a> - Minor translation issue on Farthest</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/pull/160">#160</a> - Minor translation issue on APP_ERROR</p></li>
@ -460,8 +484,8 @@
<p>This release contains several fixes including security fixes.<br />Thanks to &#64;DanielSiersleben for the report.</p>
<p>And from now on, admin account is not created on application initialization.<br />A new command is added to set administration rights on the account created after registration
(see <a class="reference external" href="https://samr1.github.io/FitTrackee/installation.html#upgrade">documentation</a>)</p>
<section id="id10">
<h3>Issues Closed<a class="headerlink" href="#id10" title="Permalink to this headline"></a></h3>
<section id="id12">
<h3>Issues Closed<a class="headerlink" href="#id12" title="Permalink to this headline"></a></h3>
<section id="misc">
<h4>Misc<a class="headerlink" href="#misc" title="Permalink to this headline"></a></h4>
<ul class="simple">
@ -469,8 +493,8 @@
</ul>
</section>
</section>
<section id="id11">
<h3>Pull Requests<a class="headerlink" href="#id11" title="Permalink to this headline"></a></h3>
<section id="id13">
<h3>Pull Requests<a class="headerlink" href="#id13" title="Permalink to this headline"></a></h3>
<section id="security">
<h4>Security<a class="headerlink" href="#security" title="Permalink to this headline"></a></h4>
<ul class="simple">
@ -488,8 +512,8 @@
</li>
</ul>
</section>
<section id="id12">
<h4>Misc<a class="headerlink" href="#id12" title="Permalink to this headline"></a></h4>
<section id="id14">
<h4>Misc<a class="headerlink" href="#id14" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/pull/152">#152</a> - Fixes and improvements:</p>
<ul>
@ -505,17 +529,17 @@
</section>
<section id="version-0-5-6-2022-02-05">
<h2>Version 0.5.6 (2022/02/05)<a class="headerlink" href="#version-0-5-6-2022-02-05" title="Permalink to this headline"></a></h2>
<section id="id13">
<h3>Issues Closed<a class="headerlink" href="#id13" title="Permalink to this headline"></a></h3>
<section id="id14">
<h4>Bugs Fixed<a class="headerlink" href="#id14" title="Permalink to this headline"></a></h4>
<section id="id15">
<h3>Issues Closed<a class="headerlink" href="#id15" title="Permalink to this headline"></a></h3>
<section id="id16">
<h4>Bugs Fixed<a class="headerlink" href="#id16" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/146">#146</a> - incorrect label on workouts filters</p></li>
</ul>
</section>
</section>
<section id="id15">
<h3>Pull Requests<a class="headerlink" href="#id15" title="Permalink to this headline"></a></h3>
<section id="id17">
<h3>Pull Requests<a class="headerlink" href="#id17" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/pull/145">#145</a> - fix on database models</p></li>
</ul>
@ -524,8 +548,8 @@
</section>
<section id="version-0-5-5-2022-01-19">
<h2>Version 0.5.5 (2022/01/19)<a class="headerlink" href="#version-0-5-5-2022-01-19" title="Permalink to this headline"></a></h2>
<section id="id16">
<h3>Issues Closed<a class="headerlink" href="#id16" title="Permalink to this headline"></a></h3>
<section id="id18">
<h3>Issues Closed<a class="headerlink" href="#id18" title="Permalink to this headline"></a></h3>
<section id="new-features">
<h4>New Features<a class="headerlink" href="#new-features" title="Permalink to this headline"></a></h4>
<ul class="simple">
@ -535,8 +559,8 @@
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/134">#134</a> - Wind direction</p></li>
</ul>
</section>
<section id="id17">
<h4>Bugs Fixed<a class="headerlink" href="#id17" title="Permalink to this headline"></a></h4>
<section id="id19">
<h4>Bugs Fixed<a class="headerlink" href="#id19" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/commit/877fa0faaabc0130402638905fe04f84563eb278">877fa0f</a> - fix sport icon color (when changed) on calendar on small resolutions</p></li>
</ul>
@ -546,10 +570,10 @@
</section>
<section id="version-0-5-4-2022-01-01">
<h2>Version 0.5.4 (2022/01/01)<a class="headerlink" href="#version-0-5-4-2022-01-01" title="Permalink to this headline"></a></h2>
<section id="id18">
<h3>Issues Closed<a class="headerlink" href="#id18" title="Permalink to this headline"></a></h3>
<section id="id19">
<h4>Bugs Fixed<a class="headerlink" href="#id19" title="Permalink to this headline"></a></h4>
<section id="id20">
<h3>Issues Closed<a class="headerlink" href="#id20" title="Permalink to this headline"></a></h3>
<section id="id21">
<h4>Bugs Fixed<a class="headerlink" href="#id21" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/131">#131</a> - No workouts displayed on calendar</p></li>
</ul>
@ -559,10 +583,10 @@
</section>
<section id="version-0-5-3-2022-01-01">
<h2>Version 0.5.3 (2022/01/01)<a class="headerlink" href="#version-0-5-3-2022-01-01" title="Permalink to this headline"></a></h2>
<section id="id20">
<h3>Issues Closed<a class="headerlink" href="#id20" title="Permalink to this headline"></a></h3>
<section id="id21">
<h4>Bugs Fixed<a class="headerlink" href="#id21" title="Permalink to this headline"></a></h4>
<section id="id22">
<h3>Issues Closed<a class="headerlink" href="#id22" title="Permalink to this headline"></a></h3>
<section id="id23">
<h4>Bugs Fixed<a class="headerlink" href="#id23" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/129">#129</a> - Display only active sports when editing a workout</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/127">#127</a> - parse_email_url() cant validate a legitimate EMAIL_URI such as “smtp://localhost:25”</p></li>
@ -573,10 +597,10 @@
</section>
<section id="version-0-5-2-2021-12-19">
<h2>Version 0.5.2 (2021/12/19)<a class="headerlink" href="#version-0-5-2-2021-12-19" title="Permalink to this headline"></a></h2>
<section id="id22">
<h3>Issues Closed<a class="headerlink" href="#id22" title="Permalink to this headline"></a></h3>
<section id="id23">
<h4>New Features<a class="headerlink" href="#id23" title="Permalink to this headline"></a></h4>
<section id="id24">
<h3>Issues Closed<a class="headerlink" href="#id24" title="Permalink to this headline"></a></h3>
<section id="id25">
<h4>New Features<a class="headerlink" href="#id25" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/123">#123</a> - Allow user to reset preferences for a sport</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/121">#121</a> - Add activity : snowshoes</p></li>
@ -587,10 +611,10 @@
</section>
<section id="version-0-5-1-2021-11-30">
<h2>Version 0.5.1 (2021/11/30)<a class="headerlink" href="#version-0-5-1-2021-11-30" title="Permalink to this headline"></a></h2>
<section id="id24">
<h3>Issues Closed<a class="headerlink" href="#id24" title="Permalink to this headline"></a></h3>
<section id="id25">
<h4>New Features<a class="headerlink" href="#id25" title="Permalink to this headline"></a></h4>
<section id="id26">
<h3>Issues Closed<a class="headerlink" href="#id26" title="Permalink to this headline"></a></h3>
<section id="id27">
<h4>New Features<a class="headerlink" href="#id27" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/116">#116</a> - Better UI for Speed and Elevation buttons in the graph of the Workout screen</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/115">#115</a> - Add option to download the GPX file of a Workout</p></li>
@ -602,10 +626,10 @@
</section>
<section id="version-0-5-0-2021-11-14">
<h2>Version 0.5.0 (2021/11/14)<a class="headerlink" href="#version-0-5-0-2021-11-14" title="Permalink to this headline"></a></h2>
<section id="id26">
<h3>Issues Closed<a class="headerlink" href="#id26" title="Permalink to this headline"></a></h3>
<section id="id27">
<h4>New Features<a class="headerlink" href="#id27" title="Permalink to this headline"></a></h4>
<section id="id28">
<h3>Issues Closed<a class="headerlink" href="#id28" title="Permalink to this headline"></a></h3>
<section id="id29">
<h4>New Features<a class="headerlink" href="#id29" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/99">#99</a> - Display workout with imperial units</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/91">#91</a> - Display elevation chart with min and max altitude of workout</p></li>
@ -613,21 +637,21 @@
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/18">#18</a> - Better UI</p></li>
</ul>
</section>
<section id="id28">
<h4>Bugs Fixed<a class="headerlink" href="#id28" title="Permalink to this headline"></a></h4>
<section id="id30">
<h4>Bugs Fixed<a class="headerlink" href="#id30" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/95">#95</a> - Some workouts seem to be missing on statistics chart</p></li>
</ul>
</section>
<section id="id29">
<h4>Misc<a class="headerlink" href="#id29" title="Permalink to this headline"></a></h4>
<section id="id31">
<h4>Misc<a class="headerlink" href="#id31" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/104">#104</a> - Switch to AGPLv3 license</p></li>
</ul>
</section>
</section>
<section id="id30">
<h3>Pull Requests<a class="headerlink" href="#id30" title="Permalink to this headline"></a></h3>
<section id="id32">
<h3>Pull Requests<a class="headerlink" href="#id32" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/pull/101">#101</a> - Docker updates for full files</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/pull/100">#100</a> - Add client application in docker for development</p></li>
@ -644,17 +668,17 @@
</section>
<section id="version-0-4-9-2021-07-16">
<h2>Version 0.4.9 (2021/07/16)<a class="headerlink" href="#version-0-4-9-2021-07-16" title="Permalink to this headline"></a></h2>
<section id="id31">
<h3>Issues Closed<a class="headerlink" href="#id31" title="Permalink to this headline"></a></h3>
<section id="id32">
<h4>New Features<a class="headerlink" href="#id32" title="Permalink to this headline"></a></h4>
<section id="id33">
<h3>Issues Closed<a class="headerlink" href="#id33" title="Permalink to this headline"></a></h3>
<section id="id34">
<h4>New Features<a class="headerlink" href="#id34" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/83">#83</a> - allow using configured tile server to generate static maps<br /><strong>Note</strong>: to keep using the default tile server, set environment variable <code class="docutils literal notranslate"><span class="pre">DEFAULT_STATICMAP</span></code> to <code class="docutils literal notranslate"><span class="pre">True</span></code></p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/81">#81</a> - display remaining characters in textarea</p></li>
</ul>
</section>
<section id="id33">
<h4>Bugs Fixed<a class="headerlink" href="#id33" title="Permalink to this headline"></a></h4>
<section id="id35">
<h4>Bugs Fixed<a class="headerlink" href="#id35" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/82">#82</a> - a user can not modify his birth day</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/80">#80</a> - can not save notes with control characters</p></li>
@ -665,10 +689,10 @@
</section>
<section id="version-0-4-8-2021-07-03">
<h2>Version 0.4.8 (2021/07/03)<a class="headerlink" href="#version-0-4-8-2021-07-03" title="Permalink to this headline"></a></h2>
<section id="id34">
<h3>Issues Closed<a class="headerlink" href="#id34" title="Permalink to this headline"></a></h3>
<section id="id35">
<h4>Bugs Fixed<a class="headerlink" href="#id35" title="Permalink to this headline"></a></h4>
<section id="id36">
<h3>Issues Closed<a class="headerlink" href="#id36" title="Permalink to this headline"></a></h3>
<section id="id37">
<h4>Bugs Fixed<a class="headerlink" href="#id37" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/79">#79</a> - Fails to start after make rebuild</p></li>
</ul>
@ -678,17 +702,17 @@
</section>
<section id="version-0-4-7-2021-04-07">
<h2>Version 0.4.7 (2021/04/07)<a class="headerlink" href="#version-0-4-7-2021-04-07" title="Permalink to this headline"></a></h2>
<section id="id36">
<h3>Issues Closed<a class="headerlink" href="#id36" title="Permalink to this headline"></a></h3>
<section id="id37">
<h4>Bugs Fixed<a class="headerlink" href="#id37" title="Permalink to this headline"></a></h4>
<section id="id38">
<h3>Issues Closed<a class="headerlink" href="#id38" title="Permalink to this headline"></a></h3>
<section id="id39">
<h4>Bugs Fixed<a class="headerlink" href="#id39" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/75">#75</a> - Workouts on the same day are not displayed in right order</p></li>
</ul>
</section>
</section>
<section id="id38">
<h3>Misc<a class="headerlink" href="#id38" title="Permalink to this headline"></a></h3>
<section id="id40">
<h3>Misc<a class="headerlink" href="#id40" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>Update Python and Javascript dependencies<br /><strong>IMPORTANT</strong>: Due to <a class="reference external" href="https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html#change-3687655465c25a39b968b4f5f6e9170b">SQLAlchemy update (1.4+)</a>, engine URLs starting with <code class="docutils literal notranslate"><span class="pre">postgres://</span></code> are no longer supported. Please update <code class="docutils literal notranslate"><span class="pre">DATABASE_URL</span></code> with <code class="docutils literal notranslate"><span class="pre">postgresql://</span></code>.</p></li>
</ul>
@ -697,10 +721,10 @@
</section>
<section id="version-0-4-6-2021-02-21">
<h2>Version 0.4.6 (2021/02/21)<a class="headerlink" href="#version-0-4-6-2021-02-21" title="Permalink to this headline"></a></h2>
<section id="id39">
<h3>Issues Closed<a class="headerlink" href="#id39" title="Permalink to this headline"></a></h3>
<section id="id40">
<h4>Bugs Fixed<a class="headerlink" href="#id40" title="Permalink to this headline"></a></h4>
<section id="id41">
<h3>Issues Closed<a class="headerlink" href="#id41" title="Permalink to this headline"></a></h3>
<section id="id42">
<h4>Bugs Fixed<a class="headerlink" href="#id42" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/72">#72</a> - Error message when file exceeding size is incorrect</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/71">#71</a> - max size or max number of files must be greater than 0</p></li>
@ -712,10 +736,10 @@
</section>
<section id="version-0-4-5-2021-02-17">
<h2>Version 0.4.5 (2021/02/17)<a class="headerlink" href="#version-0-4-5-2021-02-17" title="Permalink to this headline"></a></h2>
<section id="id41">
<h3>Issues Closed<a class="headerlink" href="#id41" title="Permalink to this headline"></a></h3>
<section id="id42">
<h4>Bugs Fixed<a class="headerlink" href="#id42" title="Permalink to this headline"></a></h4>
<section id="id43">
<h3>Issues Closed<a class="headerlink" href="#id43" title="Permalink to this headline"></a></h3>
<section id="id44">
<h4>Bugs Fixed<a class="headerlink" href="#id44" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/66">#66</a> - invalid gpx limit used when importing zip archive</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/64">#64</a> - Only 50 workouts per month shown in calendar</p></li>
@ -726,17 +750,17 @@
</section>
<section id="version-0-4-4-2021-01-31">
<h2>Version 0.4.4 (2021/01/31)<a class="headerlink" href="#version-0-4-4-2021-01-31" title="Permalink to this headline"></a></h2>
<section id="id43">
<h3>Issues Closed<a class="headerlink" href="#id43" title="Permalink to this headline"></a></h3>
<section id="id44">
<h4>Bugs Fixed<a class="headerlink" href="#id44" title="Permalink to this headline"></a></h4>
<section id="id45">
<h3>Issues Closed<a class="headerlink" href="#id45" title="Permalink to this headline"></a></h3>
<section id="id46">
<h4>Bugs Fixed<a class="headerlink" href="#id46" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/62">#62</a> - Error when sending reset password email</p></li>
</ul>
</section>
</section>
<section id="id45">
<h3>Misc<a class="headerlink" href="#id45" title="Permalink to this headline"></a></h3>
<section id="id47">
<h3>Misc<a class="headerlink" href="#id47" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>Refactoring before introducing new features.</p></li>
<li><p>Add docker files for evaluation purposes.</p></li>
@ -746,16 +770,16 @@
</section>
<section id="version-0-4-3-2021-01-10">
<h2>Version 0.4.3 (2021/01/10)<a class="headerlink" href="#version-0-4-3-2021-01-10" title="Permalink to this headline"></a></h2>
<section id="id46">
<h3>Issues Closed<a class="headerlink" href="#id46" title="Permalink to this headline"></a></h3>
<section id="id47">
<h4>New Features<a class="headerlink" href="#id47" title="Permalink to this headline"></a></h4>
<section id="id48">
<h3>Issues Closed<a class="headerlink" href="#id48" title="Permalink to this headline"></a></h3>
<section id="id49">
<h4>New Features<a class="headerlink" href="#id49" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/58">#58</a> - Standardize terms used for workouts<br /><strong>Note:</strong> Database model, upload directory for workouts and API endpoints are also updated.</p></li>
</ul>
</section>
<section id="id48">
<h4>Bugs Fixed<a class="headerlink" href="#id48" title="Permalink to this headline"></a></h4>
<section id="id50">
<h4>Bugs Fixed<a class="headerlink" href="#id50" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/59">#59</a> - No message displayed on uploading image error</p></li>
</ul>
@ -765,18 +789,18 @@
</section>
<section id="version-0-4-2-2021-01-03">
<h2>Version 0.4.2 (2021/01/03)<a class="headerlink" href="#version-0-4-2-2021-01-03" title="Permalink to this headline"></a></h2>
<section id="id49">
<h3>Misc<a class="headerlink" href="#id49" title="Permalink to this headline"></a></h3>
<section id="id51">
<h3>Misc<a class="headerlink" href="#id51" title="Permalink to this headline"></a></h3>
<p>No new features in this release, only some refactorings before introducing
new features.</p>
</section>
</section>
<section id="version-0-4-1-2020-12-31">
<h2>Version 0.4.1 (2020/12/31)<a class="headerlink" href="#version-0-4-1-2020-12-31" title="Permalink to this headline"></a></h2>
<section id="id50">
<h3>Issues Closed<a class="headerlink" href="#id50" title="Permalink to this headline"></a></h3>
<section id="id51">
<h4>New Features<a class="headerlink" href="#id51" title="Permalink to this headline"></a></h4>
<section id="id52">
<h3>Issues Closed<a class="headerlink" href="#id52" title="Permalink to this headline"></a></h3>
<section id="id53">
<h4>New Features<a class="headerlink" href="#id53" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/57">#57</a> - Use uuid for activities</p></li>
</ul>
@ -792,10 +816,10 @@ new features.</p>
<li><p>Its now possible to change the tile provider for maps. The default tile server is now <strong>OpenStreetMap</strong>s standard tile layer (replacing <strong>ThunderForest Outdoors</strong>),
see <a class="reference external" href="https://samr1.github.io/FitTrackee/installation.html#map-tile-server">Map tile server in documentation</a>.</p></li>
</ul>
<section id="id52">
<h3>Issues Closed<a class="headerlink" href="#id52" title="Permalink to this headline"></a></h3>
<section id="id53">
<h4>New Features<a class="headerlink" href="#id53" title="Permalink to this headline"></a></h4>
<section id="id54">
<h3>Issues Closed<a class="headerlink" href="#id54" title="Permalink to this headline"></a></h3>
<section id="id55">
<h4>New Features<a class="headerlink" href="#id55" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/54">#54</a> - Tile server can be changed</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/53">#53</a> - Simplify FitTrackee installation</p></li>
@ -811,10 +835,10 @@ see <a class="reference external" href="https://samr1.github.io/FitTrackee/insta
<li><p>FitTrackee administration is now available (see <a class="reference external" href="https://samr1.github.io/FitTrackee/features.html#administration">documentation</a>)<br />⚠️ Warning: some application parameters move from environment variables to database (see <a class="reference external" href="https://samr1.github.io/FitTrackee/installation.html#environment-variables">installation</a>).</p></li>
<li><p>in order to send emails, Redis is now a mandatory dependency</p></li>
</ul>
<section id="id54">
<h3>Issues Closed<a class="headerlink" href="#id54" title="Permalink to this headline"></a></h3>
<section id="id55">
<h4>New Features<a class="headerlink" href="#id55" title="Permalink to this headline"></a></h4>
<section id="id56">
<h3>Issues Closed<a class="headerlink" href="#id56" title="Permalink to this headline"></a></h3>
<section id="id57">
<h4>New Features<a class="headerlink" href="#id57" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/50">#50</a> - A user can reset his password</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/17">#17</a> - A user can delete his account</p></li>
@ -826,8 +850,8 @@ see <a class="reference external" href="https://samr1.github.io/FitTrackee/insta
</section>
<section id="version-0-2-5-fix-and-improvements-2020-01-31">
<h2>Version 0.2.5 - Fix and improvements (2020/01/31)<a class="headerlink" href="#version-0-2-5-fix-and-improvements-2020-01-31" title="Permalink to this headline"></a></h2>
<section id="id56">
<h3>Misc<a class="headerlink" href="#id56" title="Permalink to this headline"></a></h3>
<section id="id58">
<h3>Misc<a class="headerlink" href="#id58" title="Permalink to this headline"></a></h3>
<p>This version contains minor fix and improvements on client side:</p>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/commit/4c3fc343d51b9c27d3ebab71df648bcf7d7bae59">4c3fc34</a> - empty user data on logout</p></li>
@ -840,10 +864,10 @@ add URL interceptors to simplify routes definition</p></li>
</section>
<section id="version-0-2-4-minor-fix-2020-01-30">
<h2>Version 0.2.4 - Minor fix (2020/01/30)<a class="headerlink" href="#version-0-2-4-minor-fix-2020-01-30" title="Permalink to this headline"></a></h2>
<section id="id57">
<h3>Issues Closed<a class="headerlink" href="#id57" title="Permalink to this headline"></a></h3>
<section id="id58">
<h4>Bugs Fixed<a class="headerlink" href="#id58" title="Permalink to this headline"></a></h4>
<section id="id59">
<h3>Issues Closed<a class="headerlink" href="#id59" title="Permalink to this headline"></a></h3>
<section id="id60">
<h4>Bugs Fixed<a class="headerlink" href="#id60" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/47">#47</a> - timezone drop-down is not displayed correctly</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/46">#46</a> - calendar cannot display more than 5 or 6 activities on the same day</p></li>
@ -854,17 +878,17 @@ add URL interceptors to simplify routes definition</p></li>
</section>
<section id="version-0-2-3-fittrackee-available-in-french-2019-12-29">
<h2>Version 0.2.3 - FitTrackee available in French (2019/12/29)<a class="headerlink" href="#version-0-2-3-fittrackee-available-in-french-2019-12-29" title="Permalink to this headline"></a></h2>
<section id="id59">
<h3>Issues Closed<a class="headerlink" href="#id59" title="Permalink to this headline"></a></h3>
<section id="id60">
<h4>New Features<a class="headerlink" href="#id60" title="Permalink to this headline"></a></h4>
<section id="id61">
<h3>Issues Closed<a class="headerlink" href="#id61" title="Permalink to this headline"></a></h3>
<section id="id62">
<h4>New Features<a class="headerlink" href="#id62" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/43">#43</a> - Display weekend days with a different background color on calendar</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/40">#40</a> - Localize FitTrackee (i18n)</p></li>
</ul>
</section>
<section id="id61">
<h4>Bugs Fixed<a class="headerlink" href="#id61" title="Permalink to this headline"></a></h4>
<section id="id63">
<h4>Bugs Fixed<a class="headerlink" href="#id63" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/44">#44</a> - Cannot edit an activity that does not have a gpx file</p></li>
</ul>
@ -874,10 +898,10 @@ add URL interceptors to simplify routes definition</p></li>
</section>
<section id="version-0-2-2-statistics-fix-2019-09-23">
<h2>Version 0.2.2 - Statistics fix (2019/09/23)<a class="headerlink" href="#version-0-2-2-statistics-fix-2019-09-23" title="Permalink to this headline"></a></h2>
<section id="id62">
<h3>Issues Closed<a class="headerlink" href="#id62" title="Permalink to this headline"></a></h3>
<section id="id63">
<h4>Bugs Fixed<a class="headerlink" href="#id63" title="Permalink to this headline"></a></h4>
<section id="id64">
<h3>Issues Closed<a class="headerlink" href="#id64" title="Permalink to this headline"></a></h3>
<section id="id65">
<h4>Bugs Fixed<a class="headerlink" href="#id65" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/41">#41</a> - User statistics are incorrect</p></li>
</ul>
@ -887,10 +911,10 @@ add URL interceptors to simplify routes definition</p></li>
</section>
<section id="version-0-2-1-fix-and-improvements-2019-09-01">
<h2>Version 0.2.1 - Fix and improvements (2019/09/01)<a class="headerlink" href="#version-0-2-1-fix-and-improvements-2019-09-01" title="Permalink to this headline"></a></h2>
<section id="id64">
<h3>Issues Closed<a class="headerlink" href="#id64" title="Permalink to this headline"></a></h3>
<section id="id65">
<h4>New Features<a class="headerlink" href="#id65" title="Permalink to this headline"></a></h4>
<section id="id66">
<h3>Issues Closed<a class="headerlink" href="#id66" title="Permalink to this headline"></a></h3>
<section id="id67">
<h4>New Features<a class="headerlink" href="#id67" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/4">#4</a> - Show points on the map when mouse over the chart</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/14">#14</a> - Display segments informations</p></li>
@ -901,15 +925,15 @@ add URL interceptors to simplify routes definition</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/37">#37</a> - Display map on activities list</p></li>
</ul>
</section>
<section id="id66">
<h4>Bugs Fixed<a class="headerlink" href="#id66" title="Permalink to this headline"></a></h4>
<section id="id68">
<h4>Bugs Fixed<a class="headerlink" href="#id68" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/34">#34</a> - Weather is not displayed anymore</p></li>
</ul>
</section>
</section>
<section id="id67">
<h3>Misc<a class="headerlink" href="#id67" title="Permalink to this headline"></a></h3>
<section id="id69">
<h3>Misc<a class="headerlink" href="#id69" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p><strong><a class="reference external" href="https://poetry.eustace.io/">Poetry</a></strong> replaces <strong><a class="reference external" href="https://docs.pipenv.org">pipenv</a></strong> for Python packages management</p></li>
</ul>
@ -918,17 +942,17 @@ add URL interceptors to simplify routes definition</p></li>
</section>
<section id="version-0-2-0-statistics-2019-07-07">
<h2>Version 0.2.0 - Statistics (2019/07/07)<a class="headerlink" href="#version-0-2-0-statistics-2019-07-07" title="Permalink to this headline"></a></h2>
<section id="id68">
<h3>Issues Closed<a class="headerlink" href="#id68" title="Permalink to this headline"></a></h3>
<section id="id69">
<h4>New Features<a class="headerlink" href="#id69" title="Permalink to this headline"></a></h4>
<section id="id70">
<h3>Issues Closed<a class="headerlink" href="#id70" title="Permalink to this headline"></a></h3>
<section id="id71">
<h4>New Features<a class="headerlink" href="#id71" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/13">#13</a> - Detailed statistics</p></li>
</ul>
</section>
</section>
<section id="id70">
<h3>Misc<a class="headerlink" href="#id70" title="Permalink to this headline"></a></h3>
<section id="id72">
<h3>Misc<a class="headerlink" href="#id72" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>Update dependencies</p></li>
</ul>
@ -937,17 +961,17 @@ add URL interceptors to simplify routes definition</p></li>
</section>
<section id="version-0-1-1-fix-and-improvements-2019-02-07">
<h2>Version 0.1.1 - Fix and improvements (2019/02/07)<a class="headerlink" href="#version-0-1-1-fix-and-improvements-2019-02-07" title="Permalink to this headline"></a></h2>
<section id="id71">
<h3>Issues Closed<a class="headerlink" href="#id71" title="Permalink to this headline"></a></h3>
<section id="id72">
<h4>New Features<a class="headerlink" href="#id72" title="Permalink to this headline"></a></h4>
<section id="id73">
<h3>Issues Closed<a class="headerlink" href="#id73" title="Permalink to this headline"></a></h3>
<section id="id74">
<h4>New Features<a class="headerlink" href="#id74" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/25">#25</a> - Display records on calendar</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/22">#22</a> - Add a total on current month statistics</p></li>
</ul>
</section>
<section id="id73">
<h4>Bugs Fixed<a class="headerlink" href="#id73" title="Permalink to this headline"></a></h4>
<section id="id75">
<h4>Bugs Fixed<a class="headerlink" href="#id75" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/31">#31</a> - Use moving duration for stats</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/29">#29</a> - Pause duration calculation with segments</p></li>
@ -996,10 +1020,10 @@ add URL interceptors to simplify routes definition</p></li>
<li><p>no administration for now</p></li>
</ul>
<p>➡️ more informations: see <a class="reference external" href="https://samr1.github.io/FitTrackee/">documentation</a> and <a class="reference external" href="https://github.com/SamR1/FitTrackee/issues">current issues</a></p>
<section id="id74">
<h3>Issues Closed<a class="headerlink" href="#id74" title="Permalink to this headline"></a></h3>
<section id="id75">
<h4>New Features<a class="headerlink" href="#id75" title="Permalink to this headline"></a></h4>
<section id="id76">
<h3>Issues Closed<a class="headerlink" href="#id76" title="Permalink to this headline"></a></h3>
<section id="id77">
<h4>New Features<a class="headerlink" href="#id77" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/11">#11</a> - Timezone support</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/10">#10</a> - Add a note to an activity</p></li>

236
docs/cli.html Normal file
View File

@ -0,0 +1,236 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Command line interface &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
<link rel="stylesheet" type="text/css" href="_static/custom.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="API documentation" href="api/index.html" />
<link rel="prev" title="Installation" href="installation.html" />
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
<meta name="apple-mobile-web-app-capable" content="yes">
<script type="text/javascript" src="_static/js/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="_static/js/jquery-fix.js"></script>
<script type="text/javascript" src="_static/bootstrap-3.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript" src="_static/bootstrap-sphinx.js"></script>
</head><body>
<div id="navbar" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<!-- .btn-navbar is used as the toggle for collapsed navbar content -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
<div class="collapse navbar-collapse nav-collapse">
<ul class="nav navbar-nav">
<li><a href="https://github.com/SamR1/FitTrackee">GitHub</a></li>
<li class="dropdown globaltoc-container">
<a role="button"
id="dLabelGlobalToc"
data-toggle="dropdown"
data-target="#"
href="index.html">Docs <b class="caret"></b></a>
<ul class="dropdown-menu globaltoc"
role="menu"
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="api/index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a></li>
</ul>
</ul>
</li>
<li class="dropdown">
<a role="button"
id="dLabelLocalToc"
data-toggle="dropdown"
data-target="#"
href="#">Page <b class="caret"></b></a>
<ul class="dropdown-menu localtoc"
role="menu"
aria-labelledby="dLabelLocalToc"><ul>
<li><a class="reference internal" href="#">Command line interface</a><ul>
<li><a class="reference internal" href="#database">Database</a><ul>
<li><a class="reference internal" href="#ftcli-db-upgrade"><code class="docutils literal notranslate"><span class="pre">ftcli</span> <span class="pre">db</span> <span class="pre">upgrade</span></code></a></li>
<li><a class="reference internal" href="#ftcli-db-drop"><code class="docutils literal notranslate"><span class="pre">ftcli</span> <span class="pre">db</span> <span class="pre">drop</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#users">Users</a><ul>
<li><a class="reference internal" href="#ftcli-users-update"><code class="docutils literal notranslate"><span class="pre">ftcli</span> <span class="pre">users</span> <span class="pre">update</span></code></a></li>
</ul>
</li>
</ul>
</li>
</ul>
</ul>
</li>
<li>
<a href="installation.html" title="Previous Chapter: Installation"><span class="glyphicon glyphicon-chevron-left visible-sm"></span><span class="hidden-sm hidden-tablet">&laquo; Installation</span>
</a>
</li>
<li>
<a href="api/index.html" title="Next Chapter: API documentation"><span class="glyphicon glyphicon-chevron-right visible-sm"></span><span class="hidden-sm hidden-tablet">API documentation &raquo;</span>
</a>
</li>
<li class="hidden-sm">
<div id="sourcelink">
<a href="_sources/cli.rst.txt"
rel="nofollow">Source</a>
</div></li>
</ul>
<form class="navbar-form navbar-right" action="search.html" method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" />
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="body col-md-12 content" role="main">
<section id="command-line-interface">
<h1>Command line interface<a class="headerlink" href="#command-line-interface" title="Permalink to this headline"></a></h1>
<p>A command line interface (CLI) is available to manage database and users.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ftcli
Usage: ftcli <span class="o">[</span>OPTIONS<span class="o">]</span> COMMAND <span class="o">[</span>ARGS<span class="o">]</span>...
FitTrackee Command Line Interface
Options:
--help Show this message and exit.
Commands:
db Manage database.
users Manage users.
</pre></div>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<div class="line-block">
<div class="line">The following commands are now deprecated and will be removed in a next version:</div>
<div class="line">- <code class="docutils literal notranslate"><span class="pre">fittrackee_set_admin</span></code></div>
<div class="line">- <code class="docutils literal notranslate"><span class="pre">fittrackee_upgrade_db</span></code></div>
</div>
</div>
<section id="database">
<h2>Database<a class="headerlink" href="#database" title="Permalink to this headline"></a></h2>
<section id="ftcli-db-upgrade">
<h3><code class="docutils literal notranslate"><span class="pre">ftcli</span> <span class="pre">db</span> <span class="pre">upgrade</span></code><a class="headerlink" href="#ftcli-db-upgrade" title="Permalink to this headline"></a></h3>
<div class="versionadded">
<p><span class="versionmodified added">New in version 0.6.5.</span></p>
</div>
<p>Apply migrations.</p>
</section>
<section id="ftcli-db-drop">
<h3><code class="docutils literal notranslate"><span class="pre">ftcli</span> <span class="pre">db</span> <span class="pre">drop</span></code><a class="headerlink" href="#ftcli-db-drop" title="Permalink to this headline"></a></h3>
<div class="versionadded">
<p><span class="versionmodified added">New in version 0.6.5.</span></p>
</div>
<p>Empty database and delete uploaded files, only on development environments.</p>
</section>
</section>
<section id="users">
<h2>Users<a class="headerlink" href="#users" title="Permalink to this headline"></a></h2>
<section id="ftcli-users-update">
<h3><code class="docutils literal notranslate"><span class="pre">ftcli</span> <span class="pre">users</span> <span class="pre">update</span></code><a class="headerlink" href="#ftcli-users-update" title="Permalink to this headline"></a></h3>
<div class="versionadded">
<p><span class="versionmodified added">New in version 0.6.5.</span></p>
</div>
<p>Modify a user account (admin rights, active status, email and password).</p>
<table class="colwidths-given table-bordered docutils align-default">
<colgroup>
<col style="width: 33%" />
<col style="width: 67%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>Options</p></th>
<th class="head"><p>Description</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">--set-admin</span> <span class="pre">BOOLEAN</span></code></p></td>
<td><p>Add/remove admin rights (when adding admin rights, it also activates user account if not active).</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">--activate</span></code></p></td>
<td><p>Activate user account.</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">--reset-password</span></code></p></td>
<td><p>Reset user password (a new password will be displayed).</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">--update-email</span> <span class="pre">EMAIL</span></code></p></td>
<td><p>Update user email.</p></td>
</tr>
</tbody>
</table>
</section>
</section>
</section>
</div>
</div>
</div>
<footer class="footer">
<div class="container">
<p class="pull-right">
<a href="#">Back to top</a>
</p>
<p>
&copy; Copyright 2018 - 2022, SamR1.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.5.0.<br/>
</p>
</div>
</footer>
</body>
</html>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Features &#8212; FitTrackee 0.6.4
<title>Features &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1 current"><a class="current reference internal" href="#">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="api/index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a></li>
@ -233,11 +234,12 @@
<h2>Account &amp; preferences<a class="headerlink" href="#account-preferences" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p>A user can create, update and deleted his account.</p></li>
<li><p>After registration, the user account is inactive and an email with confirmation instructions is sent to activate it. A user with an inactive account cannot log in. (<em>new in 0.6.0</em>)</p></li>
<li><p>After registration, the user account is inactive and an email with confirmation instructions is sent to activate it.
A user with an inactive account cannot log in. (<em>new in 0.6.0</em>)</p></li>
</ul>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The command line to add admin rights activates the account if it is inactive.</p>
<p>In case email sending is not configured, a <a class="reference external" href="cli.html#ftcli-users-update">command line</a> allows to activate users account.</p>
</div>
<ul class="simple">
<li><p>A user can set language, timezone and first day of week.</p></li>
@ -280,6 +282,10 @@
<p class="admonition-title">Warning</p>
<p>Updating server configuration may be necessary to handle large files (like <a class="reference external" href="https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size">nginx</a> for instance).</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If email sending is disabled, a warning is displayed.</p>
</div>
</li>
<li><p><strong>Users</strong></p>
<ul class="simple">
@ -289,7 +295,7 @@
<li><p>add/remove administration rights</p></li>
<li><p>activate his account (<em>new in 0.6.0</em>)</p></li>
<li><p>update his email (in case his account is locked) (<em>new in 0.6.0</em>)</p></li>
<li><p>reset his password (in case his account is locked) (<em>new in 0.6.0</em>)</p></li>
<li><p>reset his password (in case his account is locked) (<em>new in 0.6.0</em>). If email sending is disabled, it is only possible via CLI.</p></li>
</ul>
</dd>
</dl>

View File

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Index &#8212; FitTrackee 0.6.4
<title>Index &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -37,7 +37,7 @@
</button>
<a class="navbar-brand" href="index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -58,6 +58,7 @@
aria-labelledby="dLabelGlobalToc"><ul>
<li class="toctree-l1"><a class="reference internal" href="features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="api/index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a></li>

View File

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>HTTP Routing Table &#8212; FitTrackee 0.6.4
<title>HTTP Routing Table &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -44,7 +44,7 @@
</button>
<a class="navbar-brand" href="index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -65,6 +65,7 @@
aria-labelledby="dLabelGlobalToc"><ul>
<li class="toctree-l1"><a class="reference internal" href="features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="api/index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a></li>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>FitTrackee &#8212; FitTrackee 0.6.4
<title>FitTrackee &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -39,7 +39,7 @@
</button>
<a class="navbar-brand" href="#">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -60,6 +60,7 @@
aria-labelledby="dLabelGlobalToc"><ul>
<li class="toctree-l1"><a class="reference internal" href="features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="api/index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a></li>
@ -153,6 +154,7 @@ Map</a>.</div>
<ul>
<li class="toctree-l1"><a class="reference internal" href="features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="api/index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a></li>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Installation &#8212; FitTrackee 0.6.4
<title>Installation &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -16,7 +16,7 @@
<script src="_static/doctools.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="API documentation" href="api/index.html" />
<link rel="next" title="Command line interface" href="cli.html" />
<link rel="prev" title="Features" href="features.html" />
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="features.html">Features</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="api/index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a></li>
@ -123,7 +124,7 @@
</a>
</li>
<li>
<a href="api/index.html" title="Next Chapter: API documentation"><span class="glyphicon glyphicon-chevron-right visible-sm"></span><span class="hidden-sm hidden-tablet">API documentation &raquo;</span>
<a href="cli.html" title="Next Chapter: Command line interface"><span class="glyphicon glyphicon-chevron-right visible-sm"></span><span class="hidden-sm hidden-tablet">Command line ... &raquo;</span>
</a>
</li>
@ -191,9 +192,8 @@
<ul class="simple">
<li><p>Python 3.7+</p></li>
<li><p>PostgreSQL database (10+)</p></li>
<li><p>SMTP provider</p></li>
<li><p>Redis for task queue (to send emails)</p></li>
<li><p>API key from <a class="reference external" href="https://darksky.net/dev">Dark Sky</a> [not mandatory]</p></li>
<li><p>SMTP provider and Redis for task queue (if email sending is enabled)</p></li>
<li><p>API key from <a class="reference external" href="https://darksky.net/dev">Dark Sky</a> (not mandatory)</p></li>
<li><p><a class="reference external" href="https://poetry.eustace.io">Poetry</a> (for installation from sources only)</p></li>
<li><p><a class="reference external" href="https://yarnpkg.com">Yarn</a> (for development only)</p></li>
<li><p>Docker and Docker Compose (for development or evaluation purposes)</p></li>
@ -352,6 +352,18 @@ see <a class="reference external" href="https://docs.sqlalchemy.org/en/13/core/p
<p><span class="versionmodified added">New in version 0.3.0.</span></p>
</div>
<p>Email URL with credentials, see <a class="reference external" href="installation.html#emails">Emails</a>.</p>
<div class="versionchanged">
<p><span class="versionmodified changed">Changed in version 0.6.5.</span></p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Default</dt>
<dd class="field-odd"><p>empty string</p>
</dd>
</dl>
<div class="admonition danger">
<p class="admonition-title">Danger</p>
<p>If the email URL is empty, email sending will be disabled.</p>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>If the email URL is invalid, the application may not start.</p>
@ -468,8 +480,8 @@ see <a class="reference external" href="https://docs.sqlalchemy.org/en/13/core/p
<div class="line">- Sending emails with Office365 may not work if SMTP auth is disabled.</div>
</div>
</div>
<div class="versionadded">
<p><span class="versionmodified added">New in version 0.5.3.</span></p>
<div class="versionchanged">
<p><span class="versionmodified changed">Changed in version 0.5.3.</span></p>
</div>
<div class="line-block">
<div class="line">Credentials can be omitted: <code class="docutils literal notranslate"><span class="pre">smtp://smtp.example.com:25</span></code>.</div>
@ -488,6 +500,13 @@ see <a class="reference external" href="https://docs.sqlalchemy.org/en/13/core/p
<li><p>email change (to old and new email adresses)</p></li>
<li><p>password change</p></li>
</ul>
<div class="versionchanged">
<p><span class="versionmodified changed">Changed in version 0.6.5.</span></p>
</div>
<div class="line-block">
<div class="line">For single-user instance, it is possible to disable email sending with an empty <code class="docutils literal notranslate"><span class="pre">EMAIL_URL</span></code> (in this case, no need to start dramatiq workers).</div>
<div class="line">A <a class="reference external" href="cli.html#ftcli-users-update">CLI</a> is available to activate account and modify email and password.</div>
</div>
</section>
<section id="map-tile-server">
<h3>Map tile server<a class="headerlink" href="#map-tile-server" title="Permalink to this headline"></a></h3>
@ -552,7 +571,7 @@ $ <span class="nb">source</span> .env
<ul class="simple">
<li><p>Initialize database schema</p></li>
</ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ fittrackee_upgrade_db
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ftcli db upgrade
</pre></div>
</div>
<ul class="simple">
@ -562,7 +581,7 @@ $ <span class="nb">source</span> .env
</pre></div>
</div>
<ul class="simple">
<li><p>Start task queue workers</p></li>
<li><p>Start task queue workers if email sending is enabled.</p></li>
</ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ fittrackee_worker --processes <span class="m">2</span>
</pre></div>
@ -577,7 +596,7 @@ $ <span class="nb">source</span> .env
<li><p>Open <a class="reference external" href="http://localhost:3000">http://localhost:3000</a> and register</p></li>
<li><p>To set admin rights to the newly created account, use the following command line:</p></li>
</ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ fittrackee_set_admin &lt;username&gt;
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ftcli users update &lt;username&gt; --set-admin <span class="nb">true</span>
</pre></div>
</div>
<div class="admonition note">
@ -638,7 +657,7 @@ $ make install-db
<li><p>Open <a class="reference external" href="http://localhost:3000">http://localhost:3000</a> and register</p></li>
<li><p>To set admin rights to the newly created account, use the following command line:</p></li>
</ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make set-admin <span class="nv">USERNAME</span><span class="o">=</span>&lt;username&gt;
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make user-set-admin <span class="nv">USERNAME</span><span class="o">=</span>&lt;username&gt;
</pre></div>
</div>
<div class="admonition note">
@ -655,11 +674,11 @@ $ make install-db
</div>
</div>
<ul class="simple">
<li><p>Download the last release (for now, it is the release v0.6.4):</p></li>
<li><p>Download the last release (for now, it is the release v0.6.5):</p></li>
</ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.4.tar.gz
$ tar -xzf v0.6.4.tar.gz
$ mv FitTrackee-0.6.4 FitTrackee
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.5.tar.gz
$ tar -xzf v0.6.5.tar.gz
$ mv FitTrackee-0.6.5 FitTrackee
$ <span class="nb">cd</span> FitTrackee
</pre></div>
</div>
@ -684,11 +703,15 @@ database credentials</strong>):</p></li>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make run
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If email sending is disabled: <code class="docutils literal notranslate"><span class="pre">$</span> <span class="pre">make</span> <span class="pre">run-server</span></code></p>
</div>
<ul class="simple">
<li><p>Open <a class="reference external" href="http://localhost:5000">http://localhost:5000</a> and register</p></li>
<li><p>To set admin rights to the newly created account, use the following command line:</p></li>
</ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make set-admin <span class="nv">USERNAME</span><span class="o">=</span>&lt;username&gt;
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make user-set-admin <span class="nv">USERNAME</span><span class="o">=</span>&lt;username&gt;
</pre></div>
</div>
<div class="admonition note">
@ -727,11 +750,11 @@ $ <span class="nb">source</span> .env
<ul class="simple">
<li><p>Upgrade database if needed (see changelog for migrations):</p></li>
</ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ fittrackee_upgrade_db
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ftcli db upgrade
</pre></div>
</div>
<ul class="simple">
<li><p>Restart the application and task queue workers.</p></li>
<li><p>Restart the application and task queue workers (if email sending is enabled).</p></li>
</ul>
</section>
<section id="id3">
@ -775,11 +798,11 @@ $ <span class="nb">source</span> .env
<ul class="simple">
<li><p>Stop the application</p></li>
<li><p>Change to the directory where FitTrackee directory is located</p></li>
<li><p>Download the last release (for now, it is the release v0.6.4) and overwrite existing files:</p></li>
<li><p>Download the last release (for now, it is the release v0.6.5) and overwrite existing files:</p></li>
</ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.4.tar.gz
$ tar -xzf v0.6.4.tar.gz
$ cp -R FitTrackee-0.6.4/* FitTrackee/
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.5.tar.gz
$ tar -xzf v0.6.5.tar.gz
$ cp -R FitTrackee-0.6.5/* FitTrackee/
$ <span class="nb">cd</span> FitTrackee
</pre></div>
</div>
@ -802,6 +825,10 @@ $ <span class="nb">cd</span> FitTrackee
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make run
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If email sending is disabled: <code class="docutils literal notranslate"><span class="pre">$</span> <span class="pre">make</span> <span class="pre">run-server</span></code></p>
</div>
</section>
</section>
</section>

Binary file not shown.

View File

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Search &#8212; FitTrackee 0.6.4
<title>Search &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -44,7 +44,7 @@
</button>
<a class="navbar-brand" href="index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -65,6 +65,7 @@
aria-labelledby="dLabelGlobalToc"><ul>
<li class="toctree-l1"><a class="reference internal" href="features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="api/index.html">API documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="troubleshooting/index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a></li>

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Administrator &#8212; FitTrackee 0.6.4
<title>Administrator &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/index.html">API documentation</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Troubleshooting &#8212; FitTrackee 0.6.4
<title>Troubleshooting &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/index.html">API documentation</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>User &#8212; FitTrackee 0.6.4
<title>User &#8212; FitTrackee 0.6.5
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="../index.html">
FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.4
<span class="navbar-text navbar-version pull-left"><b>0.6.5
</b></span>
</div>
@ -61,6 +61,7 @@
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../features.html">Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cli.html">Command line interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/index.html">API documentation</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Change log</a></li>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 KiB

After

Width:  |  Height:  |  Size: 539 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 KiB

After

Width:  |  Height:  |  Size: 369 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 103 KiB

67
docsrc/source/cli.rst Normal file
View File

@ -0,0 +1,67 @@
Command line interface
######################
A command line interface (CLI) is available to manage database and users.
.. code-block:: bash
$ ftcli
Usage: ftcli [OPTIONS] COMMAND [ARGS]...
FitTrackee Command Line Interface
Options:
--help Show this message and exit.
Commands:
db Manage database.
users Manage users.
.. warning::
| The following commands are now deprecated and will be removed in a next version:
| - ``fittrackee_set_admin``
| - ``fittrackee_upgrade_db``
Database
~~~~~~~~
``ftcli db upgrade``
""""""""""""""""""""
.. versionadded:: 0.6.5
Apply migrations.
``ftcli db drop``
"""""""""""""""""
.. versionadded:: 0.6.5
Empty database and delete uploaded files, only on development environments.
Users
~~~~~
``ftcli users update``
""""""""""""""""""""""
.. versionadded:: 0.6.5
Modify a user account (admin rights, active status, email and password).
.. cssclass:: table-bordered
.. list-table::
:widths: 25 50
:header-rows: 1
* - Options
- Description
* - ``--set-admin BOOLEAN``
- Add/remove admin rights (when adding admin rights, it also activates user account if not active).
* - ``--activate``
- Activate user account.
* - ``--reset-password``
- Reset user password (a new password will be displayed).
* - ``--update-email EMAIL``
- Update user email.

View File

@ -60,10 +60,11 @@ Workouts
Account & preferences
^^^^^^^^^^^^^^^^^^^^^
- A user can create, update and deleted his account.
- After registration, the user account is inactive and an email with confirmation instructions is sent to activate it. A user with an inactive account cannot log in. (*new in 0.6.0*)
- After registration, the user account is inactive and an email with confirmation instructions is sent to activate it.
A user with an inactive account cannot log in. (*new in 0.6.0*)
.. note::
The command line to add admin rights activates the account if it is inactive.
In case email sending is not configured, a `command line <cli.html#ftcli-users-update>`__ allows to activate users account.
- A user can set language, timezone and first day of week.
- A user can reset his password (*new in 0.3.0*)
@ -97,6 +98,9 @@ Administration
.. warning::
Updating server configuration may be necessary to handle large files (like `nginx <https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size>`_ for instance).
.. note::
If email sending is disabled, a warning is displayed.
- **Users**
@ -105,7 +109,7 @@ Administration
- add/remove administration rights
- activate his account (*new in 0.6.0*)
- update his email (in case his account is locked) (*new in 0.6.0*)
- reset his password (in case his account is locked) (*new in 0.6.0*)
- reset his password (in case his account is locked) (*new in 0.6.0*). If email sending is disabled, it is only possible via CLI.
- delete a user
- **Sports**

View File

@ -34,6 +34,7 @@ Table of contents
features
installation
cli
api/index
troubleshooting/index
changelog

View File

@ -22,9 +22,8 @@ Prerequisites
- Python 3.7+
- PostgreSQL database (10+)
- SMTP provider
- Redis for task queue (to send emails)
- API key from `Dark Sky <https://darksky.net/dev>`__ [not mandatory]
- SMTP provider and Redis for task queue (if email sending is enabled)
- API key from `Dark Sky <https://darksky.net/dev>`__ (not mandatory)
- `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
- `Yarn <https://yarnpkg.com>`__ (for development only)
- Docker and Docker Compose (for development or evaluation purposes)
@ -133,6 +132,13 @@ deployment method.
Email URL with credentials, see `Emails <installation.html#emails>`__.
.. versionchanged:: 0.6.5
:default: empty string
.. danger::
If the email URL is empty, email sending will be disabled.
.. warning::
If the email URL is invalid, the application may not start.
@ -214,7 +220,7 @@ To send emails, a valid ``EMAIL_URL`` must be provided:
| - If the email URL is invalid, the application may not start.
| - Sending emails with Office365 may not work if SMTP auth is disabled.
.. versionadded:: 0.5.3
.. versionchanged:: 0.5.3
| Credentials can be omitted: ``smtp://smtp.example.com:25``.
| If ``:<port>`` is omitted, the port defaults to 25.
@ -229,6 +235,11 @@ Emails sent by FitTrackee are:
- email change (to old and new email adresses)
- password change
.. versionchanged:: 0.6.5
| For single-user instance, it is possible to disable email sending with an empty ``EMAIL_URL`` (in this case, no need to start dramatiq workers).
| A `CLI <cli.html#ftcli-users-update>`__ is available to activate account and modify email and password.
Map tile server
^^^^^^^^^^^^^^^
@ -288,7 +299,7 @@ For instance, copy and update ``.env`` file from ``.env.example`` and source the
.. code-block:: bash
$ fittrackee_upgrade_db
$ ftcli db upgrade
- Start the application
@ -296,7 +307,7 @@ For instance, copy and update ``.env`` file from ``.env.example`` and source the
$ fittrackee
- Start task queue workers
- Start task queue workers if email sending is enabled.
.. code-block:: bash
@ -311,7 +322,7 @@ For instance, copy and update ``.env`` file from ``.env.example`` and source the
.. code:: bash
$ fittrackee_set_admin <username>
$ ftcli users update <username> --set-admin true
.. note::
If the user account is inactive, it activates it.
@ -373,7 +384,7 @@ Dev environment
.. code:: bash
$ make set-admin USERNAME=<username>
$ make user-set-admin USERNAME=<username>
.. note::
If the user account is inactive, it activates it.
@ -384,13 +395,13 @@ Production environment
.. warning::
| Note that FitTrackee is under heavy development, some features may be unstable.
- Download the last release (for now, it is the release v0.6.4):
- Download the last release (for now, it is the release v0.6.5):
.. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.4.tar.gz
$ tar -xzf v0.6.4.tar.gz
$ mv FitTrackee-0.6.4 FitTrackee
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.5.tar.gz
$ tar -xzf v0.6.5.tar.gz
$ mv FitTrackee-0.6.5 FitTrackee
$ cd FitTrackee
- Create **.env** from example and update it
@ -415,13 +426,16 @@ Production environment
$ make run
.. note::
If email sending is disabled: ``$ make run-server``
- Open http://localhost:5000 and register
- To set admin rights to the newly created account, use the following command line:
.. code:: bash
$ make set-admin USERNAME=<username>
$ make user-set-admin USERNAME=<username>
.. note::
If the user account is inactive, it activates it.
@ -457,9 +471,9 @@ From PyPI
.. code-block:: bash
$ fittrackee_upgrade_db
$ ftcli db upgrade
- Restart the application and task queue workers.
- Restart the application and task queue workers (if email sending is enabled).
From sources
@ -507,13 +521,13 @@ Prod environment
- Change to the directory where FitTrackee directory is located
- Download the last release (for now, it is the release v0.6.4) and overwrite existing files:
- Download the last release (for now, it is the release v0.6.5) and overwrite existing files:
.. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.4.tar.gz
$ tar -xzf v0.6.4.tar.gz
$ cp -R FitTrackee-0.6.4/* FitTrackee/
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.5.tar.gz
$ tar -xzf v0.6.5.tar.gz
$ cp -R FitTrackee-0.6.5/* FitTrackee/
$ cd FitTrackee
- Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__).
@ -536,6 +550,8 @@ Prod environment
$ make run
.. note::
If email sending is disabled: ``$ make run-server``
Deployment
~~~~~~~~~~

View File

@ -1,7 +1,6 @@
import logging
import os
import re
import shutil
from importlib import import_module, reload
from typing import Any
@ -21,7 +20,7 @@ from sqlalchemy.exc import ProgrammingError
from fittrackee.emails.email import EmailService
from fittrackee.request import CustomRequest
VERSION = __version__ = '0.6.4'
VERSION = __version__ = '0.6.5'
db = SQLAlchemy()
bcrypt = Bcrypt()
migrate = Migrate()
@ -42,7 +41,7 @@ class CustomFlask(Flask):
request_class = CustomRequest
def create_app() -> Flask:
def create_app(init_email: bool = True) -> Flask:
# instantiate the app
app = CustomFlask(
__name__, static_folder='dist/static', template_folder='dist'
@ -65,8 +64,15 @@ def create_app() -> Flask:
migrate.init_app(app, db)
dramatiq.init_app(app)
# set up email
email_service.init_email(app)
# set up email if 'EMAIL_URL' is initialized
if init_email:
if app.config['EMAIL_URL']:
email_service.init_email(app)
app.config['CAN_SEND_EMAILS'] = True
else:
appLog.warning(
'EMAIL_URL is not provided, email sending is deactivated.'
)
# get configuration from database
from .application.utils import (
@ -147,17 +153,4 @@ def create_app() -> Flask:
else:
return render_template('index.html')
@app.cli.command('drop-db')
def drop_db() -> None:
"""Empty database and delete uploaded files for dev environments."""
if app_settings == 'fittrackee.config.ProductionConfig':
print('This is a production server, aborting!')
return
db.engine.execute("DROP TABLE IF EXISTS alembic_version;")
db.drop_all()
db.session.commit()
print('Database dropped.')
shutil.rmtree(app.config['UPLOAD_FOLDER'], ignore_errors=True)
print('Uploaded files deleted.')
return app

View File

@ -3,16 +3,23 @@
import os
from typing import Dict, Optional
import click
import gunicorn.app.base
from flask import Flask
from flask_migrate import upgrade
from fittrackee import create_app
from fittrackee.users.exceptions import UserNotFoundException
from fittrackee.users.utils.admin import UserManagerService
HOST = os.getenv('HOST', '0.0.0.0')
PORT = os.getenv('PORT', '5000')
WORKERS = os.getenv('APP_WORKERS', 1)
BASEDIR = os.path.abspath(os.path.dirname(__file__))
WARNING_MESSAGE = (
"\nThis command is deprecated, it will be removed in a next version.\n"
"Please use ftcli instead.\n"
)
app = create_app()
@ -37,7 +44,39 @@ class StandaloneApplication(gunicorn.app.base.BaseApplication):
return self.application
# DEPRECATED COMMANDS
@click.group()
def users_cli() -> None:
pass
@users_cli.command('set_admin')
@click.argument('username')
def set_admin(username: str) -> None:
"""
[deprecated] Set admin rights for given user.
It will be removed in a next version.
"""
print(WARNING_MESSAGE)
with app.app_context():
try:
user_manager_service = UserManagerService(username)
user_manager_service.update(
is_admin=True,
)
print(f"User '{username}' updated.")
except UserNotFoundException:
print(f"User '{username}' not found.")
def upgrade_db() -> None:
"""
[deprecated] Apply migrations.
It will be removed in a next version.
"""
print(WARNING_MESSAGE)
with app.app_context():
upgrade(directory=BASEDIR + '/migrations')

View File

@ -42,12 +42,13 @@ def get_application_config() -> Union[Dict, HttpResponse]:
"data": {
"admin_contact": "admin@example.com",
"gpx_limit_import": 10,
"is_email_sending_enabled": true,
"is_registration_enabled": false,
"max_single_file_size": 1048576,
"max_users": 0,
"max_zip_file_size": 10485760,
"map_attribution": "&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"
"version": "0.6.4"
"version": "0.6.5"
},
"status": "success"
}
@ -91,12 +92,13 @@ def update_application_config(auth_user: User) -> Union[Dict, HttpResponse]:
"data": {
"admin_contact": "admin@example.com",
"gpx_limit_import": 10,
"is_email_sending_enabled": true,
"is_registration_enabled": false,
"max_single_file_size": 1048576,
"max_users": 10,
"max_zip_file_size": 10485760,
"map_attribution": "&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"
"version": "0.6.4"
"version": "0.6.5"
},
"status": "success"
}

View File

@ -46,6 +46,7 @@ class AppConfig(BaseModel):
return {
'admin_contact': self.admin_contact,
'gpx_limit_import': self.gpx_limit_import,
'is_email_sending_enabled': current_app.config['CAN_SEND_EMAILS'],
'is_registration_enabled': self.is_registration_enabled,
'max_single_file_size': self.max_single_file_size,
'max_zip_file_size': self.max_zip_file_size,

View File

@ -0,0 +1,14 @@
import click
from fittrackee.migrations.commands import db_cli
from fittrackee.users.commands import users_cli
@click.group()
def cli() -> None:
"""FitTrackee Command Line Interface"""
pass
cli.add_command(db_cli)
cli.add_command(users_cli)

3
fittrackee/cli/app.py Normal file
View File

@ -0,0 +1,3 @@
from fittrackee import create_app
app = create_app(init_email=False)

View File

@ -29,6 +29,7 @@ class BaseConfig:
UI_URL = os.environ.get('UI_URL')
EMAIL_URL = os.environ.get('EMAIL_URL')
SENDER_EMAIL = os.environ.get('SENDER_EMAIL')
CAN_SEND_EMAILS = False
DRAMATIQ_BROKER = broker
TILE_SERVER = {
'URL': os.environ.get(

View File

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"/><link rel="stylesheet" href="/static/css/leaflet.css"/><title>FitTrackee</title><script defer="defer" src="/static/js/chunk-vendors.6b8389c5.js"></script><script defer="defer" src="/static/js/app.756f8c8c.js"></script><link href="/static/css/app.3729aa92.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"/><link rel="stylesheet" href="/static/css/leaflet.css"/><title>FitTrackee</title><script defer="defer" src="/static/js/chunk-vendors.6b8389c5.js"></script><script defer="defer" src="/static/js/app.2222dbc7.js"></script><link href="/static/css/app.e8b7692c.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[845],{4264:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(5793),a=r(2715),s=r(3577),u=r(2119),o=r(7167),c=r(8602),i=r(9917);const l={key:0,id:"account-confirmation",class:"center-card with-margin"},E={class:"error-message"};var d=(0,n.aZ)({setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),d=(0,i.o)(),S=(0,n.Fl)((()=>d.getters[c.SY.GETTERS.ERROR_MESSAGES])),_=(0,n.Fl)((()=>t.query.token));function m(){_.value?d.dispatch(c.YN.ACTIONS.CONFIRM_ACCOUNT,{token:_.value}):r.push("/")}return(0,n.wF)((()=>m())),(0,n.Ah)((()=>d.commit(c.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(e,t)=>{const r=(0,n.up)("router-link");return(0,a.SU)(S)?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n.Wm)(r,{class:"links",to:"/account-confirmation/resend"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("buttons.ACCOUNT-CONFIRMATION-RESEND"))+"? ",1)])),_:1})])])):(0,n.kq)("",!0)}}}),S=r(3744);const _=(0,S.Z)(d,[["__scopeId","data-v-785df978"]]);var m=_},8160:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(5793),a=r(2715),s=r(3577),u=r(2119),o=r(7167),c=r(8602),i=r(9917);const l={key:0,id:"email-update",class:"center-card with-margin"},E={class:"error-message"};var d=(0,n.aZ)({setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),d=(0,i.o)(),S=(0,n.Fl)((()=>d.getters[c.YN.GETTERS.AUTH_USER_PROFILE])),_=(0,n.Fl)((()=>d.getters[c.YN.GETTERS.IS_AUTHENTICATED])),m=(0,n.Fl)((()=>d.getters[c.SY.GETTERS.ERROR_MESSAGES])),R=(0,n.Fl)((()=>t.query.token));function T(){R.value?d.dispatch(c.YN.ACTIONS.CONFIRM_EMAIL,{token:R.value,refreshUser:_.value}):r.push("/")}return(0,n.wF)((()=>T())),(0,n.Ah)((()=>d.commit(c.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(0,n.YP)((()=>m.value),(e=>{S.value.username&&e&&r.push("/")})),(e,t)=>{const r=(0,n.up)("router-link"),u=(0,n.up)("i18n-t");return(0,a.SU)(m)&&!(0,a.SU)(S).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n._)("span",null,[(0,n.Wm)(u,{keypath:"user.PROFILE.ERRORED_EMAIL_UPDATE"},{default:(0,n.w5)((()=>[(0,n.Wm)(r,{to:"/login"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("user.LOG_IN")),1)])),_:1})])),_:1})])])])):(0,n.kq)("",!0)}}}),S=r(3744);const _=(0,S.Z)(d,[["__scopeId","data-v-8c2ec9ce"]]);var m=_},6266:function(e,t,r){r.r(t),r.d(t,{default:function(){return S}});var n=r(5793),a=r(2715),s=r(8602),u=r(9917);const o=e=>((0,n.dD)("data-v-05463732"),e=e(),(0,n.Cn)(),e),c={key:0,id:"profile",class:"container view"},i=o((()=>(0,n._)("div",{id:"bottom"},null,-1)));var l=(0,n.aZ)({setup(e){const t=(0,u.o)(),r=(0,n.Fl)((()=>t.getters[s.YN.GETTERS.AUTH_USER_PROFILE]));return(e,t)=>{const s=(0,n.up)("router-view");return(0,a.SU)(r).username?((0,n.wg)(),(0,n.iD)("div",c,[(0,n.Wm)(s,{user:(0,a.SU)(r)},null,8,["user"]),i])):(0,n.kq)("",!0)}}}),E=r(3744);const d=(0,E.Z)(l,[["__scopeId","data-v-05463732"]]);var S=d},9453:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(5793),a=r(2715),s=r(2119),u=r(2179),o=r(4317),c=r(8602),i=r(9917);const l={key:0,id:"user",class:"view"},E={class:"box"};var d=(0,n.aZ)({props:{fromAdmin:{type:Boolean}},setup(e){const t=e,{fromAdmin:r}=(0,a.BK)(t),d=(0,s.yj)(),S=(0,i.o)(),_=(0,n.Fl)((()=>S.getters[c.RT.GETTERS.USER]));return(0,n.wF)((()=>{d.params.username&&"string"===typeof d.params.username&&S.dispatch(c.RT.ACTIONS.GET_USER,d.params.username)})),(0,n.Jd)((()=>{S.dispatch(c.RT.ACTIONS.EMPTY_USER)})),(e,t)=>(0,a.SU)(_).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(u.Z,{user:(0,a.SU)(_)},null,8,["user"]),(0,n._)("div",E,[(0,n.Wm)(o.Z,{user:(0,a.SU)(_),"from-admin":(0,a.SU)(r)},null,8,["user","from-admin"])])])):(0,n.kq)("",!0)}}),S=r(3744);const _=(0,S.Z)(d,[["__scopeId","data-v-af7007f4"]]);var m=_}}]);
//# sourceMappingURL=profile.6a52c2c3.js.map
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[845],{4264:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(5793),a=r(2715),s=r(3577),u=r(2119),o=r(7167),c=r(8602),i=r(9917);const l={key:0,id:"account-confirmation",class:"center-card with-margin"},E={class:"error-message"};var d=(0,n.aZ)({setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),d=(0,i.o)(),S=(0,n.Fl)((()=>d.getters[c.SY.GETTERS.ERROR_MESSAGES])),_=(0,n.Fl)((()=>t.query.token));function m(){_.value?d.dispatch(c.YN.ACTIONS.CONFIRM_ACCOUNT,{token:_.value}):r.push("/")}return(0,n.wF)((()=>m())),(0,n.Ah)((()=>d.commit(c.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(e,t)=>{const r=(0,n.up)("router-link");return(0,a.SU)(S)?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n.Wm)(r,{class:"links",to:"/account-confirmation/resend"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("buttons.ACCOUNT-CONFIRMATION-RESEND"))+"? ",1)])),_:1})])])):(0,n.kq)("",!0)}}}),S=r(3744);const _=(0,S.Z)(d,[["__scopeId","data-v-785df978"]]);var m=_},8160:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(5793),a=r(2715),s=r(3577),u=r(2119),o=r(7167),c=r(8602),i=r(9917);const l={key:0,id:"email-update",class:"center-card with-margin"},E={class:"error-message"};var d=(0,n.aZ)({setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),d=(0,i.o)(),S=(0,n.Fl)((()=>d.getters[c.YN.GETTERS.AUTH_USER_PROFILE])),_=(0,n.Fl)((()=>d.getters[c.YN.GETTERS.IS_AUTHENTICATED])),m=(0,n.Fl)((()=>d.getters[c.SY.GETTERS.ERROR_MESSAGES])),R=(0,n.Fl)((()=>t.query.token));function T(){R.value?d.dispatch(c.YN.ACTIONS.CONFIRM_EMAIL,{token:R.value,refreshUser:_.value}):r.push("/")}return(0,n.wF)((()=>T())),(0,n.Ah)((()=>d.commit(c.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(0,n.YP)((()=>m.value),(e=>{S.value.username&&e&&r.push("/")})),(e,t)=>{const r=(0,n.up)("router-link"),u=(0,n.up)("i18n-t");return(0,a.SU)(m)&&!(0,a.SU)(S).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n._)("span",null,[(0,n.Wm)(u,{keypath:"user.PROFILE.ERRORED_EMAIL_UPDATE"},{default:(0,n.w5)((()=>[(0,n.Wm)(r,{to:"/login"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("user.LOG_IN")),1)])),_:1})])),_:1})])])])):(0,n.kq)("",!0)}}}),S=r(3744);const _=(0,S.Z)(d,[["__scopeId","data-v-8c2ec9ce"]]);var m=_},6266:function(e,t,r){r.r(t),r.d(t,{default:function(){return S}});var n=r(5793),a=r(2715),s=r(8602),u=r(9917);const o=e=>((0,n.dD)("data-v-05463732"),e=e(),(0,n.Cn)(),e),c={key:0,id:"profile",class:"container view"},i=o((()=>(0,n._)("div",{id:"bottom"},null,-1)));var l=(0,n.aZ)({setup(e){const t=(0,u.o)(),r=(0,n.Fl)((()=>t.getters[s.YN.GETTERS.AUTH_USER_PROFILE]));return(e,t)=>{const s=(0,n.up)("router-view");return(0,a.SU)(r).username?((0,n.wg)(),(0,n.iD)("div",c,[(0,n.Wm)(s,{user:(0,a.SU)(r)},null,8,["user"]),i])):(0,n.kq)("",!0)}}}),E=r(3744);const d=(0,E.Z)(l,[["__scopeId","data-v-05463732"]]);var S=d},9453:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(5793),a=r(2715),s=r(2119),u=r(2179),o=r(4980),c=r(8602),i=r(9917);const l={key:0,id:"user",class:"view"},E={class:"box"};var d=(0,n.aZ)({props:{fromAdmin:{type:Boolean}},setup(e){const t=e,{fromAdmin:r}=(0,a.BK)(t),d=(0,s.yj)(),S=(0,i.o)(),_=(0,n.Fl)((()=>S.getters[c.RT.GETTERS.USER]));return(0,n.wF)((()=>{d.params.username&&"string"===typeof d.params.username&&S.dispatch(c.RT.ACTIONS.GET_USER,d.params.username)})),(0,n.Jd)((()=>{S.dispatch(c.RT.ACTIONS.EMPTY_USER)})),(e,t)=>(0,a.SU)(_).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(u.Z,{user:(0,a.SU)(_)},null,8,["user"]),(0,n._)("div",E,[(0,n.Wm)(o.Z,{user:(0,a.SU)(_),"from-admin":(0,a.SU)(r)},null,8,["user","from-admin"])])])):(0,n.kq)("",!0)}}),S=r(3744);const _=(0,S.Z)(d,[["__scopeId","data-v-af7007f4"]]);var m=_}}]);
//# sourceMappingURL=profile.52d627f4.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,44 @@
import os
import shutil
import click
from flask_migrate import upgrade
from fittrackee import db
from fittrackee.cli.app import app
BASEDIR = os.path.abspath(os.path.dirname(__file__))
app_settings = os.getenv('APP_SETTINGS', 'fittrackee.config.ProductionConfig')
@click.group(name='db')
def db_cli() -> None:
"""Manage database."""
pass
@db_cli.command('upgrade')
def upgrade_db() -> None:
"""Apply migrations."""
with app.app_context():
upgrade(directory=BASEDIR)
@db_cli.command('drop')
def drop_db() -> None:
"""Empty database and delete uploaded files for dev environments."""
with app.app_context():
if app_settings == 'fittrackee.config.ProductionConfig':
click.echo(
click.style(
'This is a production server, aborting!', bold=True
),
err=True,
)
return
db.engine.execute("DROP TABLE IF EXISTS alembic_version;")
db.drop_all()
db.session.commit()
click.echo('Database dropped.')
shutil.rmtree(app.config['UPLOAD_FOLDER'], ignore_errors=True)
click.echo('Uploaded files deleted.')

View File

@ -24,6 +24,7 @@ class TestConfigModel:
serialized_app_config['gpx_limit_import']
== app_config.gpx_limit_import
)
assert serialized_app_config['is_email_sending_enabled'] is True
assert serialized_app_config['is_registration_enabled'] is True
assert (
serialized_app_config['max_single_file_size']
@ -49,3 +50,11 @@ class TestConfigModel:
assert app_config.is_registration_enabled is False
assert serialized_app_config['is_registration_enabled'] is False
def test_it_returns_email_sending_disabled_when_no_email_url_provided(
self, app_wo_email_activation: Flask, user_1: User, user_2: User
) -> None:
app_config = AppConfig.query.first()
serialized_app_config = app_config.serialize()
assert serialized_app_config['is_email_sending_enabled'] is False

View File

@ -146,6 +146,12 @@ def app_wo_email_auth(monkeypatch: pytest.MonkeyPatch) -> Generator:
yield from get_app(with_config=True)
@pytest.fixture
def app_wo_email_activation(monkeypatch: pytest.MonkeyPatch) -> Generator:
monkeypatch.setenv('EMAIL_URL', '')
yield from get_app(with_config=True)
@pytest.fixture
def app_wo_domain() -> Generator:
yield from get_app(with_config=True)

View File

@ -294,6 +294,31 @@ class TestUserRegistration(ApiTestCaseMixin):
},
)
def test_it_does_not_call_account_confirmation_email_when_email_sending_is_disabled( # noqa
self,
app_wo_email_activation: Flask,
account_confirmation_email_mock: Mock,
) -> None:
client = app_wo_email_activation.test_client()
email = self.random_email()
username = self.random_string()
response = client.post(
'/api/auth/register',
data=json.dumps(
dict(
username=username,
email=email,
password='12345678',
)
),
content_type='application/json',
environ_base={'HTTP_USER_AGENT': USER_AGENT},
)
assert response.status_code == 200
account_confirmation_email_mock.send.assert_not_called()
@pytest.mark.parametrize(
'text_transformation',
['upper', 'lower'],
@ -773,6 +798,36 @@ class TestUserAccountUpdate(ApiTestCaseMixin):
assert new_email == user_1.email_to_confirm
assert user_1.confirmation_token is not None
def test_it_updates_email_when_email_sending_is_disabled(
self,
app_wo_email_activation: Flask,
user_1: User,
email_updated_to_current_address_mock: MagicMock,
email_updated_to_new_address_mock: MagicMock,
password_change_email_mock: MagicMock,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app_wo_email_activation, user_1.email
)
new_email = 'new.email@example.com'
response = client.patch(
'/api/auth/profile/edit/account',
content_type='application/json',
data=json.dumps(
dict(
email=new_email,
password='12345678',
)
),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
assert response.status_code == 200
assert user_1.email == new_email
assert user_1.email_to_confirm is None
assert user_1.confirmation_token is None
def test_it_calls_email_updated_to_current_email_send_when_new_email_provided( # noqa
self,
app: Flask,
@ -1107,6 +1162,37 @@ class TestUserAccountUpdate(ApiTestCaseMixin):
email_updated_to_new_address_mock.send.assert_called_once()
password_change_email_mock.send.assert_called_once()
def test_it_does_not_calls_all_email_send_when_email_sending_is_disabled(
self,
app_wo_email_activation: Flask,
user_1: User,
email_updated_to_current_address_mock: MagicMock,
email_updated_to_new_address_mock: MagicMock,
password_change_email_mock: MagicMock,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app_wo_email_activation, user_1.email
)
client.patch(
'/api/auth/profile/edit/account',
content_type='application/json',
data=json.dumps(
dict(
email='new.email@example.com',
password='12345678',
new_password=self.random_string(),
)
),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
self.assert_no_emails_sent(
email_updated_to_current_address_mock,
email_updated_to_new_address_mock,
password_change_email_mock,
)
class TestUserPreferencesUpdate(ApiTestCaseMixin):
def test_it_returns_error_if_payload_is_empty(
@ -1648,6 +1734,21 @@ class TestPasswordResetRequest(ApiTestCaseMixin):
self.assert_400(response)
def test_it_returns_error_when_email_sending_is_disabled(
self, app_wo_email_activation: Flask
) -> None:
client = app_wo_email_activation.test_client()
response = client.post(
'/api/auth/password/reset-request',
data=json.dumps(dict(email='test@test.com')),
content_type='application/json',
)
self.assert_404_with_message(
response, 'the requested URL was not found on the server'
)
def test_it_requests_password_reset_when_user_exists(
self, app: Flask, user_1: User, user_reset_password_email: Mock
) -> None:
@ -1873,7 +1974,7 @@ class TestPasswordUpdate(ApiTestCaseMixin):
assert data['status'] == 'success'
assert data['message'] == 'password updated'
def test_it_send_email_after_successful_update(
def test_it_sends_email_after_successful_update(
self,
app: Flask,
user_1: User,
@ -1908,6 +2009,29 @@ class TestPasswordUpdate(ApiTestCaseMixin):
},
)
def test_it_does_not_send_email_when_email_sending_is_disabled(
self,
app_wo_email_activation: Flask,
user_1: User,
password_change_email_mock: MagicMock,
) -> None:
token = get_user_token(user_1.id, password_reset=True)
client = app_wo_email_activation.test_client()
client.post(
'/api/auth/password/update',
data=json.dumps(
dict(
token=token,
password=self.random_string(),
)
),
content_type='application/json',
environ_base={'HTTP_USER_AGENT': USER_AGENT},
)
password_change_email_mock.send.assert_not_called()
class TestEmailUpdateWitUnauthenticatedUser(ApiTestCaseMixin):
def test_it_returns_error_if_token_is_missing(self, app: Flask) -> None:
@ -2138,3 +2262,18 @@ class TestResendAccountConfirmationEmail(ApiTestCaseMixin):
),
},
)
def test_it_returns_error_if_email_sending_is_disabled(
self, app_wo_email_activation: Flask, inactive_user: User
) -> None:
client = app_wo_email_activation.test_client()
response = client.post(
'/api/auth/account/resend-confirmation',
data=json.dumps(dict(email=inactive_user.email)),
content_type='application/json',
)
self.assert_404_with_message(
response, 'the requested URL was not found on the server'
)

View File

@ -1077,6 +1077,27 @@ class TestUpdateUser(ApiTestCaseMixin):
},
)
def test_it_does_not_call_password_change_email_when_email_sending_is_disabled( # noqa
self,
app_wo_email_activation: Flask,
user_1_admin: User,
user_2: User,
user_password_change_email_mock: MagicMock,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app_wo_email_activation, user_1_admin.email
)
response = client.patch(
f'/api/users/{user_2.username}',
content_type='application/json',
data=json.dumps(dict(reset_password=True)),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
assert response.status_code == 200
user_password_change_email_mock.send.assert_not_called()
def test_it_calls_reset_password_email_when_password_reset_is_successful(
self,
app: Flask,
@ -1118,6 +1139,27 @@ class TestUpdateUser(ApiTestCaseMixin):
},
)
def test_it_does_not_call_reset_password_email_when_email_sending_is_disabled( # noqa
self,
app_wo_email_activation: Flask,
user_1_admin: User,
user_2: User,
user_reset_password_email: MagicMock,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app_wo_email_activation, user_1_admin.email
)
response = client.patch(
f'/api/users/{user_2.username}',
content_type='application/json',
data=json.dumps(dict(reset_password=True)),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
assert response.status_code == 200
user_reset_password_email.send.assert_not_called()
def test_it_returns_error_when_updating_email_with_invalid_address(
self, app: Flask, user_1_admin: User, user_2: User
) -> None:
@ -1172,27 +1214,48 @@ class TestUpdateUser(ApiTestCaseMixin):
user_email_updated_to_new_address_mock.send.assert_not_called()
def test_it_updates_user_email(
def test_it_updates_user_email_to_confirm_when_email_sending_is_enabled(
self, app: Flask, user_1_admin: User, user_2: User
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app, user_1_admin.email
)
new_email = 'new.' + user_2.email
user_2_email = user_2.email
user_2_confirmation_token = user_2.confirmation_token
response = client.patch(
f'/api/users/{user_2.username}',
content_type='application/json',
data=json.dumps(dict(new_email='new.' + user_2.email)),
data=json.dumps(dict(new_email=new_email)),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
assert response.status_code == 200
assert user_2.email == user_2_email
assert user_2.email_to_confirm == 'new.' + user_2.email
assert user_2.email_to_confirm == new_email
assert user_2.confirmation_token != user_2_confirmation_token
def test_it_updates_user_email_when_email_sending_is_disabled(
self, app_wo_email_activation: Flask, user_1_admin: User, user_2: User
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app_wo_email_activation, user_1_admin.email
)
new_email = 'new.' + user_2.email
response = client.patch(
f'/api/users/{user_2.username}',
content_type='application/json',
data=json.dumps(dict(new_email=new_email)),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
assert response.status_code == 200
assert user_2.email == new_email
assert user_2.email_to_confirm is None
assert user_2.confirmation_token is None
def test_it_calls_email_updated_to_new_address_when_password_reset_is_successful( # noqa
self,
app: Flask,
@ -1229,6 +1292,28 @@ class TestUpdateUser(ApiTestCaseMixin):
},
)
def test_it_does_not_call_email_updated_to_new_address_when_email_sending_is_disabled( # noqa
self,
app_wo_email_activation: Flask,
user_1_admin: User,
user_2: User,
user_email_updated_to_new_address_mock: MagicMock,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app_wo_email_activation, user_1_admin.email
)
new_email = 'new.' + user_2.email
response = client.patch(
f'/api/users/{user_2.username}',
content_type='application/json',
data=json.dumps(dict(new_email=new_email)),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
assert response.status_code == 200
user_email_updated_to_new_address_mock.send.assert_not_called()
def test_it_activates_user_account(
self, app: Flask, user_1_admin: User, inactive_user: User
) -> None:

View File

@ -3,10 +3,14 @@ from unittest.mock import patch
import pytest
from flask import Flask
from fittrackee import bcrypt
from fittrackee.tests.utils import random_string
from fittrackee.users.exceptions import UserNotFoundException
from fittrackee.users.exceptions import (
InvalidEmailException,
UserNotFoundException,
)
from fittrackee.users.models import User
from fittrackee.users.utils.admin import set_admin_rights
from fittrackee.users.utils.admin import UserManagerService
from fittrackee.users.utils.controls import (
check_password,
check_username,
@ -14,37 +18,166 @@ from fittrackee.users.utils.controls import (
register_controls,
)
from ..utils import random_email
class TestSetAdminRights:
class TestUserManagerService:
def test_it_raises_exception_if_user_does_not_exist(
self, app: Flask
) -> None:
user_manager_service = UserManagerService(username=random_string())
with pytest.raises(UserNotFoundException):
set_admin_rights(random_string())
user_manager_service.update()
def test_it_does_not_update_user_when_no_args_provided(
self, app: Flask, user_1: User
) -> None:
user_manager_service = UserManagerService(username=user_1.username)
_, user_updated, _ = user_manager_service.update()
assert user_updated is False
def test_it_returns_user(self, app: Flask, user_1: User) -> None:
user_manager_service = UserManagerService(username=user_1.username)
user, _, _ = user_manager_service.update()
assert user == user_1
def test_it_sets_admin_right_for_a_given_user(
self, app: Flask, user_1: User
) -> None:
set_admin_rights(user_1.username)
user_manager_service = UserManagerService(username=user_1.username)
user_manager_service.update(is_admin=True)
assert user_1.admin is True
def test_it_return_updated_user_flag_to_true(
self, app: Flask, user_1: User
) -> None:
user_manager_service = UserManagerService(username=user_1.username)
_, user_updated, _ = user_manager_service.update(is_admin=True)
assert user_updated is True
def test_it_does_not_raise_exception_when_user_has_already_admin_right(
self, app: Flask, user_1_admin: User
) -> None:
set_admin_rights(user_1_admin.username)
user_manager_service = UserManagerService(
username=user_1_admin.username
)
user_manager_service.update(is_admin=True)
assert user_1_admin.admin is True
def test_it_activates_account_if_user_is_inactive(
self, app: Flask, inactive_user: User
) -> None:
set_admin_rights(inactive_user.username)
user_manager_service = UserManagerService(
username=inactive_user.username
)
user_manager_service.update(is_admin=True)
assert inactive_user.admin is True
assert inactive_user.is_active is True
assert inactive_user.confirmation_token is None
def test_it_activates_given_user_account(
self, app: Flask, inactive_user: User
) -> None:
user_manager_service = UserManagerService(
username=inactive_user.username
)
user_manager_service.update(activate=True)
assert inactive_user.is_active is True
def test_it_empties_confirmation_token(
self, app: Flask, inactive_user: User
) -> None:
user_manager_service = UserManagerService(
username=inactive_user.username
)
user_manager_service.update(activate=True)
assert inactive_user.confirmation_token is None
def test_it_does_not_raise_error_if_user_account_already_activated(
self, app: Flask, user_1: User
) -> None:
user_manager_service = UserManagerService(username=user_1.username)
user_manager_service.update(activate=True)
assert user_1.is_active is True
def test_it_resets_user_password(self, app: Flask, user_1: User) -> None:
previous_password = user_1.password
user_manager_service = UserManagerService(username=user_1.username)
user_manager_service.update(reset_password=True)
assert user_1.password != previous_password
def test_new_password_is_encrypted(self, app: Flask, user_1: User) -> None:
user_manager_service = UserManagerService(username=user_1.username)
_, _, new_password = user_manager_service.update(reset_password=True)
assert bcrypt.check_password_hash(user_1.password, new_password)
def test_it_raises_exception_if_provided_email_is_invalid(
self, app: Flask, user_1: User
) -> None:
user_manager_service = UserManagerService(username=user_1.username)
with pytest.raises(
InvalidEmailException, match='valid email must be provided'
):
user_manager_service.update(new_email=random_string())
def test_it_raises_exception_if_provided_email_is_current_user_email(
self, app: Flask, user_1: User
) -> None:
user_manager_service = UserManagerService(username=user_1.username)
with pytest.raises(
InvalidEmailException,
match='new email must be different than curent email',
):
user_manager_service.update(new_email=user_1.email)
def test_it_updates_user_email_to_confirm(
self, app: Flask, user_1: User
) -> None:
new_email = random_email()
current_email = user_1.email
user_manager_service = UserManagerService(username=user_1.username)
user_manager_service.update(new_email=new_email)
assert user_1.email == current_email
assert user_1.email_to_confirm == new_email
assert user_1.confirmation_token is not None
def test_it_updates_user_email(self, app: Flask, user_1: User) -> None:
new_email = random_email()
user_manager_service = UserManagerService(username=user_1.username)
user_manager_service.update(
new_email=new_email, with_confirmation=False
)
assert user_1.email == new_email
assert user_1.email_to_confirm is None
assert user_1.confirmation_token is None
class TestIsValidEmail:
@pytest.mark.parametrize(

View File

@ -40,25 +40,27 @@ from .utils.token import decode_user_token
auth_blueprint = Blueprint('auth', __name__)
HEX_COLOR_REGEX = regex = "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"
NOT_FOUND_MESSAGE = 'the requested URL was not found on the server'
def send_account_confirmation_email(user: User) -> None:
ui_url = current_app.config['UI_URL']
email_data = {
'username': user.username,
'fittrackee_url': ui_url,
'operating_system': request.user_agent.platform, # type: ignore # noqa
'browser_name': request.user_agent.browser, # type: ignore
'account_confirmation_url': (
f'{ui_url}/account-confirmation'
f'?token={user.confirmation_token}'
),
}
user_data = {
'language': 'en',
'email': user.email,
}
account_confirmation_email.send(user_data, email_data)
if current_app.config['CAN_SEND_EMAILS']:
ui_url = current_app.config['UI_URL']
email_data = {
'username': user.username,
'fittrackee_url': ui_url,
'operating_system': request.user_agent.platform, # type: ignore # noqa
'browser_name': request.user_agent.browser, # type: ignore
'account_confirmation_url': (
f'{ui_url}/account-confirmation'
f'?token={user.confirmation_token}'
),
}
user_data = {
'language': 'en',
'email': user.email,
}
account_confirmation_email.send(user_data, email_data)
@auth_blueprint.route('/auth/register', methods=['POST'])
@ -505,7 +507,7 @@ def update_user_account(auth_user: User) -> Union[Dict, HttpResponse]:
"""
update authenticated user email and password
It sends emails:
It sends emails if sending is enabled:
- Password change
- Email change:
@ -634,8 +636,12 @@ def update_user_account(auth_user: User) -> Union[Dict, HttpResponse]:
try:
if email_to_confirm != auth_user.email:
if is_valid_email(email_to_confirm):
auth_user.email_to_confirm = email_to_confirm
auth_user.confirmation_token = secrets.token_urlsafe(30)
if current_app.config['CAN_SEND_EMAILS']:
auth_user.email_to_confirm = email_to_confirm
auth_user.confirmation_token = secrets.token_urlsafe(30)
else:
auth_user.email = email_to_confirm
auth_user.confirmation_token = None
else:
error_messages = 'email: valid email must be provided\n'
@ -652,44 +658,48 @@ def update_user_account(auth_user: User) -> Union[Dict, HttpResponse]:
db.session.commit()
ui_url = current_app.config['UI_URL']
user_data = {
'language': (
'en' if auth_user.language is None else auth_user.language
),
'email': auth_user.email,
}
data = {
'username': auth_user.username,
'fittrackee_url': ui_url,
'operating_system': request.user_agent.platform,
'browser_name': request.user_agent.browser,
}
if new_password is not None:
password_change_email.send(user_data, data)
if (
auth_user.email_to_confirm is not None
and auth_user.email_to_confirm != auth_user.email
):
email_data = {
**data,
**{'new_email_address': email_to_confirm},
if current_app.config['CAN_SEND_EMAILS']:
ui_url = current_app.config['UI_URL']
user_data = {
'language': (
'en' if auth_user.language is None else auth_user.language
),
'email': auth_user.email,
}
email_updated_to_current_address.send(user_data, email_data)
email_data = {
**data,
**{
'email_confirmation_url': (
f'{ui_url}/email-update'
f'?token={auth_user.confirmation_token}'
)
},
data = {
'username': auth_user.username,
'fittrackee_url': ui_url,
'operating_system': request.user_agent.platform,
'browser_name': request.user_agent.browser,
}
user_data = {**user_data, **{'email': auth_user.email_to_confirm}}
email_updated_to_new_address.send(user_data, email_data)
if new_password is not None:
password_change_email.send(user_data, data)
if (
auth_user.email_to_confirm is not None
and auth_user.email_to_confirm != auth_user.email
):
email_data = {
**data,
**{'new_email_address': email_to_confirm},
}
email_updated_to_current_address.send(user_data, email_data)
email_data = {
**data,
**{
'email_confirmation_url': (
f'{ui_url}/email-update'
f'?token={auth_user.confirmation_token}'
)
},
}
user_data = {
**user_data,
**{'email': auth_user.email_to_confirm},
}
email_updated_to_new_address.send(user_data, email_data)
return {
'status': 'success',
@ -1139,6 +1149,8 @@ def request_password_reset() -> Union[Dict, HttpResponse]:
"""
handle password reset request
If email sending is disabled, this endpoint is not available
**Example request**:
.. sourcecode:: http
@ -1162,8 +1174,12 @@ def request_password_reset() -> Union[Dict, HttpResponse]:
:statuscode 200: password reset request processed
:statuscode 400: invalid payload
:statuscode 404: the requested URL was not found on the server
"""
if not current_app.config['CAN_SEND_EMAILS']:
return NotFoundErrorResponse(NOT_FOUND_MESSAGE)
post_data = request.get_json()
if not post_data or post_data.get('email') is None:
return InvalidPayloadErrorResponse()
@ -1203,6 +1219,8 @@ def update_password() -> Union[Dict, HttpResponse]:
"""
update user password after password reset request
It sends emails if sending is enabled
**Example request**:
.. sourcecode:: http
@ -1259,18 +1277,21 @@ def update_password() -> Union[Dict, HttpResponse]:
).decode()
db.session.commit()
password_change_email.send(
{
'language': ('en' if user.language is None else user.language),
'email': user.email,
},
{
'username': user.username,
'fittrackee_url': current_app.config['UI_URL'],
'operating_system': request.user_agent.platform,
'browser_name': request.user_agent.browser,
},
)
if current_app.config['CAN_SEND_EMAILS']:
password_change_email.send(
{
'language': (
'en' if user.language is None else user.language
),
'email': user.email,
},
{
'username': user.username,
'fittrackee_url': current_app.config['UI_URL'],
'operating_system': request.user_agent.platform,
'browser_name': request.user_agent.browser,
},
)
return {
'status': 'success',
@ -1406,6 +1427,8 @@ def resend_account_confirmation_email() -> Union[Dict, HttpResponse]:
"""
resend email with instructions to confirm account
If email sending is disabled, this endpoint is not available
**Example request**:
.. sourcecode:: http
@ -1429,9 +1452,13 @@ def resend_account_confirmation_email() -> Union[Dict, HttpResponse]:
:statuscode 200: confirmation email resent
:statuscode 400: invalid payload
:statuscode 404: the requested URL was not found on the server
:statuscode 500: error, please try again or contact the administrator
"""
if not current_app.config['CAN_SEND_EMAILS']:
return NotFoundErrorResponse(NOT_FOUND_MESSAGE)
post_data = request.get_json()
if not post_data or post_data.get('email') is None:
return InvalidPayloadErrorResponse()

View File

@ -0,0 +1,62 @@
from typing import Optional
import click
from fittrackee.cli.app import app
from fittrackee.users.exceptions import UserNotFoundException
from fittrackee.users.utils.admin import UserManagerService
@click.group(name='users')
def users_cli() -> None:
"""Manage users."""
pass
@users_cli.command('update')
@click.argument('username')
@click.option(
'--set-admin',
type=bool,
help='Add/remove admin rights (when adding admin rights, '
'it also activates user account if not active).',
)
@click.option('--activate', is_flag=True, help='Activate user account.')
@click.option(
'--reset-password',
is_flag=True,
help='Reset user password (a new password will be displayed).',
)
@click.option('--update-email', type=str, help='Update user email.')
def manage_user(
username: str,
set_admin: Optional[bool],
activate: bool,
reset_password: bool,
update_email: Optional[str],
) -> None:
"""Manage given user account."""
with app.app_context():
try:
user_manager_service = UserManagerService(username)
_, is_user_updated, password = user_manager_service.update(
is_admin=set_admin,
with_confirmation=False,
activate=activate,
reset_password=reset_password,
new_email=update_email,
)
if is_user_updated:
click.echo(f"User '{username}' updated.")
if password:
click.echo(f"The new password is: {password}")
else:
click.echo("No updates.")
except UserNotFoundException:
click.echo(
f"User '{username}' not found.\n"
"Check the provided user name (case sensitive).",
err=True,
)
except Exception as e:
click.echo(f'An error occurred: {e}', err=True)

View File

@ -1,2 +1,6 @@
class InvalidEmailException(Exception):
...
class UserNotFoundException(Exception):
...

View File

@ -1,13 +1,11 @@
import os
import secrets
import shutil
from typing import Any, Dict, Tuple, Union
import click
from flask import Blueprint, current_app, request, send_file
from sqlalchemy import exc
from fittrackee import bcrypt, db
from fittrackee import db
from fittrackee.emails.tasks import (
email_updated_to_new_address,
password_change_email,
@ -22,31 +20,19 @@ from fittrackee.responses import (
UserNotFoundErrorResponse,
handle_error_and_return_response,
)
from fittrackee.users.utils.controls import is_valid_email
from fittrackee.utils import get_readable_duration
from fittrackee.workouts.models import Record, Workout, WorkoutSegment
from .decorators import authenticate, authenticate_as_admin
from .exceptions import UserNotFoundException
from .exceptions import InvalidEmailException, UserNotFoundException
from .models import User, UserSportPreference
from .utils.admin import set_admin_rights
from .utils.admin import UserManagerService
users_blueprint = Blueprint('users', __name__)
USER_PER_PAGE = 10
@users_blueprint.cli.command('set-admin')
@click.argument('username')
def set_admin(username: str) -> None:
"""Set admin rights for given user"""
try:
set_admin_rights(username)
print(f"User '{username}' updated.")
except UserNotFoundException:
print(f"User '{username}' not found.")
@users_blueprint.route('/users', methods=['GET'])
@authenticate_as_admin
def get_users(auth_user: User) -> Dict:
@ -414,8 +400,9 @@ def update_user(auth_user: User, user_name: str) -> Union[Dict, HttpResponse]:
Update user account
- add/remove admin rights (regardless user account status)
- reset password (and send email to update user password)
- update user email (and send email to update user password)
- reset password (and send email to update user password,
if sending enabled)
- update user email (and send email to new user email, if sending enabled)
- activate account for an inactive user
Only user with admin rights can modify another user
@ -530,94 +517,77 @@ def update_user(auth_user: User, user_name: str) -> Union[Dict, HttpResponse]:
if not user_data:
return InvalidPayloadErrorResponse()
send_password_emails = False
send_new_address_email = False
try:
user = User.query.filter_by(username=user_name).first()
if not user:
return UserNotFoundErrorResponse()
reset_password = user_data.get('reset_password', False)
new_email = user_data.get('new_email')
user_manager_service = UserManagerService(username=user_name)
user, _, _ = user_manager_service.update(
is_admin=user_data.get('admin'),
activate=user_data.get('activate', False),
reset_password=reset_password,
new_email=new_email,
with_confirmation=current_app.config['CAN_SEND_EMAILS'],
)
if 'admin' in user_data:
user.admin = user_data['admin']
if user_data.get('activate', False):
user.is_active = True
user.confirmation_token = None
if user_data.get('reset_password', False):
new_password = secrets.token_urlsafe(30)
user.password = bcrypt.generate_password_hash(
new_password, current_app.config.get('BCRYPT_LOG_ROUNDS')
).decode()
send_password_emails = True
if 'new_email' in user_data:
if is_valid_email(user_data['new_email']):
if user_data['new_email'] == user.email:
return InvalidPayloadErrorResponse(
'new email must be different than curent email'
)
user.email_to_confirm = user_data['new_email']
user.confirmation_token = secrets.token_urlsafe(30)
send_new_address_email = True
else:
return InvalidPayloadErrorResponse(
'valid email must be provided'
if current_app.config['CAN_SEND_EMAILS']:
user_language = 'en' if user.language is None else user.language
ui_url = current_app.config['UI_URL']
if reset_password:
user_data = {
'language': user_language,
'email': user.email,
}
password_change_email.send(
user_data,
{
'username': user.username,
'fittrackee_url': ui_url,
},
)
password_reset_token = user.encode_password_reset_token(
user.id
)
reset_password_email.send(
user_data,
{
'expiration_delay': get_readable_duration(
current_app.config[
'PASSWORD_TOKEN_EXPIRATION_SECONDS'
],
user_language,
),
'username': user.username,
'password_reset_url': (
f'{ui_url}/password-reset?'
f'token={password_reset_token}'
),
'fittrackee_url': ui_url,
},
)
db.session.commit()
user_language = 'en' if user.language is None else user.language
ui_url = current_app.config['UI_URL']
if send_password_emails:
user_data = {
'language': user_language,
'email': user.email,
}
password_change_email.send(
user_data,
{
if new_email:
user_data = {
'language': user_language,
'email': user.email_to_confirm,
}
email_data = {
'username': user.username,
'fittrackee_url': ui_url,
},
)
password_reset_token = user.encode_password_reset_token(user.id)
reset_password_email.send(
user_data,
{
'expiration_delay': get_readable_duration(
current_app.config[
'PASSWORD_TOKEN_EXPIRATION_SECONDS'
],
user_language,
'email_confirmation_url': (
f'{ui_url}/email-update'
f'?token={user.confirmation_token}'
),
'username': user.username,
'password_reset_url': (
f'{ui_url}/password-reset?token={password_reset_token}'
),
'fittrackee_url': ui_url,
},
)
if send_new_address_email:
user_data = {
'language': user_language,
'email': user.email_to_confirm,
}
email_data = {
'username': user.username,
'fittrackee_url': ui_url,
'email_confirmation_url': (
f'{ui_url}/email-update'
f'?token={user.confirmation_token}'
),
}
email_updated_to_new_address.send(user_data, email_data)
}
email_updated_to_new_address.send(user_data, email_data)
return {
'status': 'success',
'data': {'users': [user.serialize(auth_user)]},
}
except UserNotFoundException:
return UserNotFoundErrorResponse()
except InvalidEmailException as e:
return InvalidPayloadErrorResponse(str(e))
except exc.StatementError as e:
return handle_error_and_return_response(e, db=db)

View File

@ -1,14 +1,86 @@
from fittrackee import db
import secrets
from typing import Optional, Tuple
from ..exceptions import UserNotFoundException
from flask import current_app
from fittrackee import bcrypt, db
from ..exceptions import InvalidEmailException, UserNotFoundException
from ..models import User
from ..utils.controls import is_valid_email
def set_admin_rights(username: str) -> None:
user = User.query.filter_by(username=username).first()
if not user:
raise UserNotFoundException()
user.admin = True
user.is_active = True
user.confirmation_token = None
db.session.commit()
class UserManagerService:
def __init__(self, username: str):
self.username = username
def _get_user(self) -> User:
user = User.query.filter_by(username=self.username).first()
if not user:
raise UserNotFoundException()
return user
def _update_admin_rights(self, user: User, is_admin: bool) -> None:
user.admin = is_admin
if is_admin:
self._activate_user(user)
@staticmethod
def _activate_user(user: User) -> None:
user.is_active = True
user.confirmation_token = None
@staticmethod
def _reset_user_password(user: User) -> str:
new_password = secrets.token_urlsafe(30)
user.password = bcrypt.generate_password_hash(
new_password, current_app.config.get('BCRYPT_LOG_ROUNDS')
).decode()
return new_password
@staticmethod
def _update_user_email(
user: User, new_email: str, with_confirmation: bool
) -> None:
if not is_valid_email(new_email):
raise InvalidEmailException('valid email must be provided')
if user.email == new_email:
raise InvalidEmailException(
'new email must be different than curent email'
)
if with_confirmation:
user.email_to_confirm = new_email
user.confirmation_token = secrets.token_urlsafe(30)
else:
user.email = new_email
def update(
self,
is_admin: Optional[bool] = None,
activate: bool = False,
reset_password: bool = False,
new_email: Optional[str] = None,
with_confirmation: bool = True,
) -> Tuple[User, bool, Optional[str]]:
user_updated = False
new_password = None
user = self._get_user()
if is_admin is not None:
self._update_admin_rights(user, is_admin)
user_updated = True
if activate:
self._activate_user(user)
user_updated = True
if reset_password:
new_password = self._reset_user_password(user)
user_updated = True
if new_email is not None:
self._update_user_email(user, new_email, with_confirmation)
user_updated = True
db.session.commit()
return user, user_updated, new_password

View File

@ -1,6 +1,6 @@
{
"name": "fittrackee_client",
"version": "0.6.4",
"version": "0.6.5",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",

View File

@ -11,7 +11,7 @@
{{ $t('admin.APPLICATION') }}
</router-link>
</dt>
<dd>
<dd class="application-config-details">
{{ $t('admin.UPDATE_APPLICATION_DESCRIPTION') }}<br />
<span class="registration-status">
{{
@ -22,6 +22,13 @@
)
}}
</span>
<span
class="email-sending-status"
v-if="!appConfig.is_email_sending_enabled"
>
<i class="fa fa-exclamation-triangle" aria-hidden="true" />
{{ $t('admin.EMAIL_SENDING_DISABLED') }}
</span>
</dd>
<dt>
<router-link to="/admin/sports">
@ -82,8 +89,13 @@
dd {
margin-bottom: $default-margin * 3;
}
.registration-status {
font-weight: bold;
.application-config-details {
display: flex;
flex-direction: column;
.email-sending-status,
.registration-status {
font-weight: bold;
}
}
}
}

View File

@ -93,7 +93,10 @@
{{ $t('admin.UPDATE_USER_EMAIL') }}
</button>
<button
v-if="authUser.username !== user.username"
v-if="
authUser.username !== user.username &&
appConfig.is_email_sending_enabled
"
@click.prevent="updateDisplayModal('reset')"
>
{{ $t('admin.RESET_USER_PASSWORD') }}
@ -124,6 +127,7 @@
} from 'vue'
import { AUTH_USER_STORE, ROOT_STORE, USERS_STORE } from '@/store/constants'
import { TAppConfig } from '@/types/application'
import { IAuthUserProfile, IUserProfile } from '@/types/user'
import { useStore } from '@/use/useStore'
@ -157,6 +161,9 @@
const errorMessages: ComputedRef<string | string[] | null> = computed(
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
)
const appConfig: ComputedRef<TAppConfig> = computed(
() => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]
)
let displayModal: Ref<string> = ref('')
const formErrors = ref(false)
const displayUserEmailForm: Ref<boolean> = ref(false)

View File

@ -10,7 +10,13 @@
<div class="profile-form form-box">
<ErrorMessage :message="errorMessages" v-if="errorMessages" />
<div class="info-box success-message" v-if="isSuccess">
{{ $t(`user.PROFILE.SUCCESSFUL_${emailUpdate ? 'EMAIL_' : ''}UPDATE`) }}
{{
$t(
`user.PROFILE.SUCCESSFUL_${
emailUpdate && appConfig.is_email_sending_enabled ? 'EMAIL_' : ''
}UPDATE`
)
}}
</div>
<form :class="{ errors: formErrors }" @submit.prevent="updateProfile">
<label class="form-items" for="email">
@ -77,6 +83,7 @@
import PasswordInput from '@/components/Common/PasswordInput.vue'
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
import { TAppConfig } from '@/types/application'
import { IUserProfile, IUserAccountPayload } from '@/types/user'
import { useStore } from '@/use/useStore'
@ -95,6 +102,9 @@
const loading = computed(
() => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]
)
const appConfig: ComputedRef<TAppConfig> = computed(
() => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]
)
const isSuccess: ComputedRef<boolean> = computed(
() => store.getters[AUTH_USER_STORE.GETTERS.IS_SUCCESS]
)

View File

@ -16,6 +16,10 @@
message="user.REGISTER_DISABLED"
v-if="registration_disabled"
/>
<AlertMessage
message="admin.EMAIL_SENDING_DISABLED"
v-if="sendingEmailDisabled"
/>
<div
class="info-box success-message"
v-if="isSuccess || isRegistrationSuccess"
@ -23,7 +27,11 @@
{{
$t(
`user.PROFILE.SUCCESSFUL_${
isRegistrationSuccess ? 'REGISTRATION' : 'UPDATE'
isRegistrationSuccess
? `REGISTRATION${
appConfig.is_email_sending_enabled ? '_WITH_EMAIL' : ''
}`
: 'UPDATE'
}`
)
}}
@ -52,7 +60,7 @@
<input
v-if="action !== 'reset'"
id="email"
:disabled="registration_disabled"
:disabled="registration_disabled || sendingEmailDisabled"
required
@invalid="invalidateForm"
type="email"
@ -91,7 +99,10 @@
@passwordError="invalidateForm"
/>
</div>
<button type="submit" :disabled="registration_disabled">
<button
type="submit"
:disabled="registration_disabled || sendingEmailDisabled"
>
{{ $t(buttonText) }}
</button>
</form>
@ -99,8 +110,12 @@
<router-link class="links" to="/register">
{{ $t('user.REGISTER') }}
</router-link>
-
<router-link class="links" to="/password-reset/request">
<span v-if="appConfig.is_email_sending_enabled">-</span>
<router-link
v-if="appConfig.is_email_sending_enabled"
class="links"
to="/password-reset/request"
>
{{ $t('user.PASSWORD_FORGOTTEN') }}
</router-link>
</div>
@ -110,7 +125,12 @@
{{ $t('user.LOGIN') }}
</router-link>
</div>
<div v-if="['login', 'register'].includes(action)">
<div
v-if="
['login', 'register'].includes(action) &&
appConfig.is_email_sending_enabled
"
>
<router-link class="links" to="/account-confirmation/resend">
{{ $t('user.ACCOUNT_CONFIRMATION_NOT_RECEIVED') }}
</router-link>
@ -175,6 +195,11 @@
() =>
props.action === 'register' && !appConfig.value.is_registration_enabled
)
const sendingEmailDisabled: ComputedRef<boolean> = computed(
() =>
['reset-request', 'account-confirmation-resend'].includes(props.action) &&
!appConfig.value.is_email_sending_enabled
)
const formErrors = ref(false)
function getButtonText(action: string): string {

View File

@ -21,6 +21,7 @@
"CONFIRM_USER_PASSWORD_RESET": "Are you sure you want to reset {0} password?",
"CURRENT_EMAIL": "Current email",
"DELETE_USER": "Delete user",
"EMAIL_SENDING_DISABLED": "Email sending is disabled.",
"ENABLE_DISABLE_SPORTS": "Enable/disable sports.",
"NEW_EMAIL": "New email",
"PASSWORD_RESET_SUCCESSFUL": "The password has been reset.",

View File

@ -23,7 +23,7 @@
"signature expired, please log in again": "Signature expired. Please log in again.",
"successfully registered": "Successfully registered.",
"user does not exist": "User does not exist.",
"valid email must be provided for admin contact": "A valid email must be provided for admininstrator contact",
"valid email must be provided for admin contact": "A valid email must be provided for administrator contact",
"you can not delete your account, no other user has admin rights": "You can not delete your account, no other user has admin rights.",
"you do not have permissions": "You do not have permissions."
},

View File

@ -86,7 +86,8 @@
"STOPPED_SPEED_THRESHOLD": "stopped speed threshold"
},
"SUCCESSFUL_EMAIL_UPDATE": "Your account has been updated successfully. Please check your email to confirm your new email address.",
"SUCCESSFUL_REGISTRATION": "A link to activate your account has been emailed to the address provided.",
"SUCCESSFUL_REGISTRATION": "Your account has been created successfully.",
"SUCCESSFUL_REGISTRATION_WITH_EMAIL": "A link to activate your account has been emailed to the address provided.",
"SUCCESSFUL_UPDATE": "Your account has been updated successfully.",
"UNITS": {
"LABEL": "Units for distance",

View File

@ -21,6 +21,7 @@
"CONFIRM_USER_PASSWORD_RESET": "Êtes-vous sûr de vouloir réinitialiser le mot de passe de l'utilisateur {0} ?",
"CURRENT_EMAIL": "Adresse email actuelle",
"DELETE_USER": "Supprimer l'utilisateur",
"EMAIL_SENDING_DISABLED": "L'envoi d'emails est désactivé.",
"ENABLE_DISABLE_SPORTS": "Activer/désactiver des sports.",
"NEW_EMAIL": "Nouvelle adresse email",
"PASSWORD_RESET_SUCCESSFUL": "Le mot de passe a été réinitialisé.",

View File

@ -91,7 +91,8 @@
"STOPPED_SPEED_THRESHOLD": "seuil de vitesse arrêtée"
},
"SUCCESSFUL_EMAIL_UPDATE": "Votre compte a été modifié avec succès. Veuillez vérifier votre boite email pour valider votre nouvelle adresse email.",
"SUCCESSFUL_REGISTRATION": "Un lien pour activer votre compte a été envoyé à l'adresse email fournie.",
"SUCCESSFUL_REGISTRATION": "Votre compte a été créé avec succès.",
"SUCCESSFUL_REGISTRATION_WITH_EMAIL": "Un lien pour activer votre compte a été envoyé à l'adresse email fournie.",
"SUCCESSFUL_UPDATE": "Votre compte a été modifié avec succès.",
"TIMEZONE": "Fuseau horaire"
},

View File

@ -9,6 +9,7 @@ export type TAppConfig = {
[key: string]: number | boolean | string
admin_contact: string
gpx_limit_import: number
is_email_sending_enabled: boolean
is_registration_enabled: boolean
map_attribution: string
max_single_file_size: number

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "fittrackee"
version = "0.6.4"
version = "0.6.5"
description = "Self-hosted outdoor workout/activity tracker"
authors = ["SamR1"]
license = "AGPL-3.0"
@ -63,9 +63,10 @@ Sphinx = "^4.5"
[tool.poetry.scripts]
fittrackee = 'fittrackee.__main__:main'
fittrackee_set_admin = 'fittrackee.users.users:set_admin'
fittrackee_upgrade_db = 'fittrackee.__main__:upgrade_db'
fittrackee_worker = 'flask_dramatiq:worker'
ftcli = 'fittrackee.cli:cli'
fittrackee_set_admin = 'fittrackee.__main__:set_admin' # deprecated
fittrackee_upgrade_db = 'fittrackee.__main__:upgrade_db' # deprecated
[tool.black]
line-length = 79