forked from OurHike/OurHike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpreferences.py
More file actions
54 lines (43 loc) · 2.33 KB
/
Copy pathpreferences.py
File metadata and controls
54 lines (43 loc) · 2.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
"""The `user_preferences` table - a sync target for the client-owned
`UserPreferences` model.
See ../../../features/IDENTITY_AND_PRIVACY.md (the canonical, consolidated
model - it merges what used to be five separate small settings models). That
model is PRIMARILY client-side/IndexedDB; this table only exists so a hiker
who links a real account has somewhere to sync it to, once linked (same
"local-first, syncs on linking" story as `Profile.display_name`/trail name -
see app/models/profile.py).
One row per profile. `profile_id` is both the primary key and the foreign
key back to `profiles.id` - there is exactly one preferences row per
account, never a history of them, so there's no separate surrogate id to
invent.
Most of the fields (trail_name, theme, unit_system, background_source,
max_background_zoom, show_roads, waypoint_types_shown, layer_detail_level,
auto_rotate_enabled, anonymity_window_days, onboarding_completed,
download_choice_made, location_permission_requested) live together in a
single JSON column rather than one column per field. This is a client-owned
blob that syncs wholesale, not a table anything here queries relationally
(no route filters "profiles where theme=dark") - a single JSON column means
the client-side model can gain/rename/drop a field without a migration on
this table. That's a storage-layer simplification only: the *contents* of
the blob are still strictly validated at the API boundary (see
app/schemas/preferences.py), including that `show_closures` is rejected
outright - it is deliberately not part of `UserPreferences` at all (Map
Options: closures are always shown, never hideable).
`updated_at` follows the same naive-UTC pattern as `Profile.created_at`
(see app/models/profile.py's comment): a tz-aware `datetime` is stored with
its tzinfo stripped, which is safe because every value going in is already
UTC by construction, and the designator is stamped back on at the wire.
"""
from sqlalchemy import JSON, Column, DateTime, ForeignKey, String
from app.core.time import utc_now
from app.db.base import Base
class UserPreferences(Base):
__tablename__ = "user_preferences"
profile_id = Column(String, ForeignKey("profiles.id"), primary_key=True)
data = Column(JSON, nullable=False)
updated_at = Column(
DateTime,
nullable=False,
default=utc_now,
onupdate=utc_now,
)