Skip to content

Commit a5c3091

Browse files
committed
enh(welcome): 🌟 improving the first login experience on DESKTOP incarnation #128
1 parent b241a75 commit a5c3091

17 files changed

Lines changed: 426 additions & 10 deletions

‎CHANGELOG.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ This MyTraL **minor** release brings:
88
- .
99

1010
### Added
11-
- .
11+
- Smooth first start for the desktop application: when no user profile exists
12+
yet, a default `athlete` user ("MyTraL Athlete") is auto-created and
13+
auto-logged in, landing straight on the dashboard - no sign-up/login step
14+
required. Logging out disables auto-login until the next explicit login,
15+
so a second/third user can be added or logged into from the login page.
1216

1317
### Fixed
14-
- .
18+
- Fixed path(s) in Snap which pointed outside of strict confinement filesystem.
1519

1620
### Documentation
1721
- .

‎INSTALLATION.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ Tarball:
3333
# Install
3434
Install MyTraL desktop application.
3535

36+
### First launch
37+
38+
The desktop application is ready to use right after install - no sign-up or
39+
login is needed. On the very first start, when no user profile exists yet, a
40+
default `athlete` user ("MyTraL Athlete") is created automatically and you are
41+
logged straight into the dashboard. You can rename this user, change its
42+
password, or create additional users from the profile page at any time.
43+
Logging out disables auto-login until you log back in explicitly, so the
44+
login page lets you pick an existing user or add a new one.
45+
3646

3747

3848
## Install on Ubuntu from PPA

‎docs/CHANGELOG.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ This MyTraL **minor** release brings:
88
- .
99

1010
### Added
11-
- .
11+
- Smooth first start for the desktop application: when no user profile exists
12+
yet, a default `athlete` user ("MyTraL Athlete") is auto-created and
13+
auto-logged in, landing straight on the dashboard - no sign-up/login step
14+
required. Logging out disables auto-login until the next explicit login,
15+
so a second/third user can be added or logged into from the login page.
1216

1317
### Fixed
14-
- .
18+
- Fixed path(s) in Snap which pointed outside of strict confinement filesystem.
1519

1620
### Documentation
1721
- .

‎docs/INSTALLATION.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ Tarball:
3333
# Install
3434
Install MyTraL desktop application.
3535

36+
### First launch
37+
38+
The desktop application is ready to use right after install - no sign-up or
39+
login is needed. On the very first start, when no user profile exists yet, a
40+
default `athlete` user ("MyTraL Athlete") is created automatically and you are
41+
logged straight into the dashboard. You can rename this user, change its
42+
password, or create additional users from the profile page at any time.
43+
Logging out disables auto-login until you log back in explicitly, so the
44+
login page lets you pick an existing user or add a new one.
45+
3646

3747

3848
## Install on Ubuntu from PPA

‎mytral/__init__.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"""MyTraL main module: configure and start the web application."""
1919

2020
from mytral import blobstore as _blobstore_pkg
21+
from mytral import bootstraps
2122
from mytral import config
2223
from mytral import loggers
2324
from mytral import releng
@@ -62,6 +63,12 @@
6263
app_ds = dataset.MyTraLDataset(mytral_config=app_config, logger=app_logger)
6364
# MyTraL user dataset: persistence agnostic access to the user data
6465
app_user_ds = app_ds.user()
66+
67+
# smooth first start: auto-create the default athlete user on desktop
68+
# installations which don't have any user profile yet
69+
if app_config.incarnation == config.MytralIncarnation.DESKTOP:
70+
bootstraps.bootstrap_default_desktop_user(ds=app_user_ds, logger=app_logger)
71+
6572
# blob store for activity attachments (GPX files and photos)
6673
app_blobstore = _blobstore_pkg.create_blobstore(app_config)
6774

‎mytral/backends/dataset.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ def register_new_user(
9494
self,
9595
user_name: str = commons.DEFAULT_USER_NAME,
9696
user_id: str = "",
97+
user_display_name: str = "",
9798
password_enc: str = "",
99+
auto_login: bool = False,
98100
):
99101
"""Create new user (sandbox / entries / tables).
100102
@@ -104,8 +106,13 @@ def register_new_user(
104106
Username.
105107
user_id : str
106108
Unique user ID.
109+
user_display_name : str
110+
Display name shown in the UI.
107111
password_enc : str
108112
Encrypted password.
113+
auto_login : bool
114+
Whether the new profile should have auto-login enabled
115+
(DESKTOP incarnation only).
109116
110117
"""
111118
raise NotImplementedError

‎mytral/backends/datasets/dataset_json.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,7 @@ def register_new_user(
10811081
user_id: str = "",
10821082
user_display_name: str = "",
10831083
password_enc: str = "",
1084+
auto_login: bool = False,
10841085
):
10851086
self.user_dir(user_id)
10861087

@@ -1100,6 +1101,7 @@ def register_new_user(
11001101
born_day=commons.BOOTSTRAP_BORN_DAY,
11011102
height=commons.BOOTSTRAP_HEIGHT_CM,
11021103
gender=True,
1104+
auto_login=auto_login,
11031105
)
11041106
)
11051107

‎mytral/blueprints/auth_uri_space.py‎

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from mytral import security
3232
from mytral import settings as user_settings
3333
from mytral.migrations import FsPersistenceMigrations
34+
from mytral.routes import COOKIE_AUTO_LOGIN_SUPPRESSED
3435
from mytral.routes import COOKIE_MOBILE
3536
from mytral.routes import COOKIE_TOKEN
3637
from mytral.routes import COOKIE_USER
@@ -162,6 +163,8 @@ def signup():
162163
# log user in - store user_id (UUID) not username
163164
flask.session[COOKIE_USER] = user_id
164165
flask.session[COOKIE_TOKEN] = uuid.uuid4()
166+
# a fresh, explicit login re-enables auto-login for the next boot
167+
flask.session.pop(COOKIE_AUTO_LOGIN_SUPPRESSED, None)
165168

166169
flask.flash(
167170
message=f"Welcome {new_username}! Your account has been created.",
@@ -204,7 +207,24 @@ def login():
204207

205208
auto_login_usernames = []
206209
if app_config.incarnation == config.MytralIncarnation.DESKTOP:
207-
auto_login_usernames = list(ds.list_profile_names(auto_login=True).keys())
210+
auto_login_profiles = ds.list_profile_names(auto_login=True)
211+
auto_login_usernames = list(auto_login_profiles.keys())
212+
213+
# smooth first start / single-user desktop: silently log in as the
214+
# sole auto-login user, unless the user just logged out on purpose
215+
if len(auto_login_profiles) == 1 and not flask.session.get(
216+
COOKIE_AUTO_LOGIN_SUPPRESSED, False
217+
):
218+
user_name, user_id = next(iter(auto_login_profiles.items()))
219+
220+
flask.session[COOKIE_USER] = user_id
221+
flask.session[COOKIE_TOKEN] = str(uuid.uuid4())
222+
223+
flask.flash(
224+
message=f"Auto logged in as user '{user_name}'",
225+
category="success",
226+
)
227+
return flask.redirect(flask.url_for("home"))
208228

209229
return flask.render_template(
210230
"log-in.html",
@@ -294,6 +314,8 @@ def login():
294314
flask.session[COOKIE_USER] = user_id
295315
# safe foo token to client cookies
296316
flask.session[COOKIE_TOKEN] = str(uuid.uuid4())
317+
# a fresh, explicit login re-enables auto-login for the next boot
318+
flask.session.pop(COOKIE_AUTO_LOGIN_SUPPRESSED, None)
297319

298320
# if the page width is <800px, then switch to mobile view
299321
app_logger.debug(f"Storing page width to session: {form.page_width.data}")
@@ -362,6 +384,9 @@ def logout():
362384
flask.session.pop(COOKIE_TOKEN, None)
363385
if user_id:
364386
ds.cache_evict(user_id=user_id)
387+
# desktop: suppress auto-login so the user can pick/create another account
388+
if app_config.incarnation == config.MytralIncarnation.DESKTOP:
389+
flask.session[COOKIE_AUTO_LOGIN_SUPPRESSED] = True
365390
return flask.redirect(flask.url_for("login"))
366391

367392

‎mytral/bootstraps.py‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,47 @@
1616
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1717

1818
"""Bootstrap related code."""
19+
20+
import uuid
21+
22+
from mytral import commons
23+
from mytral import loggers
24+
from mytral import security
25+
from mytral.backends import dataset
26+
27+
28+
def bootstrap_default_desktop_user(
29+
ds: dataset.UserDataset, logger: loggers.MytralStructLogger
30+
) -> None:
31+
"""Auto-create the default athlete user on the first DESKTOP boot.
32+
33+
Smooth first start: DESKTOP incarnation with no user profile on disk yet
34+
gets a default user (with auto-login enabled) so that it can go straight
35+
to the dashboard, without sign-up/login. Installations which already have
36+
at least one profile are left untouched.
37+
38+
Parameters
39+
----------
40+
ds : dataset.UserDataset
41+
User dataset used to check for existing profiles and register the
42+
default user.
43+
logger : loggers.MytralStructLogger
44+
Logger used to record that the default user was created.
45+
46+
"""
47+
if ds.list_profiles():
48+
return
49+
50+
user_id = str(uuid.uuid4())
51+
ds.register_new_user(
52+
user_name=commons.DEFAULT_DESKTOP_USER_NAME,
53+
user_id=user_id,
54+
user_display_name=commons.DEFAULT_DESKTOP_USER_DISPLAY_NAME,
55+
password_enc=security.hash_password(commons.DEFAULT_DESKTOP_USER_PASSWORD),
56+
auto_login=True,
57+
)
58+
logger.info(
59+
"Bootstrapped default desktop user",
60+
user_name=commons.DEFAULT_DESKTOP_USER_NAME,
61+
user_id=user_id,
62+
)

‎mytral/commons.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
# default user name (desktop app installation)
3030
DEFAULT_USER_NAME = "dvorka"
3131

32+
# default user auto-created on the first DESKTOP boot when no user exists yet
33+
DEFAULT_DESKTOP_USER_NAME = "athlete"
34+
DEFAULT_DESKTOP_USER_DISPLAY_NAME = "MyTraL Athlete"
35+
DEFAULT_DESKTOP_USER_PASSWORD = "changeit"
36+
3237
#
3338
# DATASETS & PERSISTENCE
3439
#

0 commit comments

Comments
 (0)