Jun 26 update to the latest codes

This commit is contained in:
2026-06-26 12:09:49 -04:00
parent 77678ed724
commit 5d95cdbbfc
15 changed files with 711 additions and 36 deletions
+2 -1
View File
@@ -5,4 +5,5 @@ from app.models.inspection import (InspectionTemplate, ChecklistItem,
from app.models.issue import Issue
from app.models.project import Project, CustomerAssignment
from app.models.api_token import RefreshToken, DeviceToken
from app.models.notification_matrix import NotificationMatrix
from app.models.notification_matrix import NotificationMatrix
from app.models.device_registration import DeviceRegistration
+15 -12
View File
@@ -10,9 +10,9 @@ RefreshToken
Revocation is instant: delete the row.
DeviceToken
One row per (user, device) pair. Stores the APNs token so the server
can push notifications to the device. Updated on every app launch
because APNs tokens can rotate.
One row per (user, device) pair. Stores device info so the admin can
see all installed devices and their versions. Updated on every app
launch because APNs tokens can rotate.
"""
import secrets
@@ -100,25 +100,28 @@ class RefreshToken(db.Model):
class DeviceToken(db.Model):
"""
APNs device token for push notification delivery.
Device record for admin tracking and optional APNs push delivery.
One row per (user, device_id) pair — upserted on every app launch.
The apns_token is the hex string returned by the iOS SDK.
apns_token is optional (empty string when APNs push is not configured).
ios_version and last_seen_at added in phase31 for the admin Devices page.
"""
__tablename__ = 'api_device_tokens'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(
db.Integer,
db.ForeignKey('users.id', ondelete='CASCADE'),
nullable=False,
index=True,
)
device_id = db.Column(db.String(64), nullable=False) # UIDevice.identifierForVendor
apns_token = db.Column(db.String(200), nullable=False)
device_name = db.Column(db.String(100), nullable=True)
app_version = db.Column(db.String(20), nullable=True)
registered_at = db.Column(db.DateTime, nullable=False, default=now_eastern)
device_id = db.Column(db.String(64), nullable=False)
apns_token = db.Column(db.String(200), nullable=False, default='')
device_name = db.Column(db.String(100), nullable=True)
app_version = db.Column(db.String(20), nullable=True)
ios_version = db.Column(db.String(20), nullable=True)
registered_at = db.Column(db.DateTime, nullable=False, default=now_eastern)
last_seen_at = db.Column(db.DateTime, nullable=True)
__table_args__ = (
db.UniqueConstraint('user_id', 'device_id', name='uq_device_token_user_device'),
+24
View File
@@ -0,0 +1,24 @@
# app/models/device_registration.py
# -----------------------------------
# Tracks iOS devices that have registered with the server.
# One row per physical device — upserted on every app foreground.
from app import db
from app.utils.time_utils import now_eastern
class DeviceRegistration(db.Model):
__tablename__ = 'device_registrations'
id = db.Column(db.Integer, primary_key=True)
# Stable UUID generated on first launch and stored in iOS Keychain.
# Unique across all devices; survives app restarts but not device wipes.
device_id = db.Column(db.String(64), nullable=False, unique=True, index=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True)
device_name = db.Column(db.String(255), nullable=False, default='')
app_version = db.Column(db.String(32), nullable=False, default='')
ios_version = db.Column(db.String(32), nullable=False, default='')
registered_at = db.Column(db.DateTime, nullable=False, default=now_eastern)
last_seen_at = db.Column(db.DateTime, nullable=False, default=now_eastern)
user = db.relationship('User', backref=db.backref('devices', lazy='dynamic'))